From 1b85b5a732f499dcd5c05a7244d777e58d7a1372 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 10 Sep 2020 11:26:18 +0200 Subject: [PATCH] Clean up code --- .../plus/server/MetaTileFileSystemCache.java | 96 ----------- .../endpoints/MetaTileFileSystemCache.java | 163 ++++++++++++++++++ .../plus/server/endpoints/TileEndpoint.java | 130 ++------------ 3 files changed, 175 insertions(+), 214 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/server/MetaTileFileSystemCache.java create mode 100644 OsmAnd/src/net/osmand/plus/server/endpoints/MetaTileFileSystemCache.java diff --git a/OsmAnd/src/net/osmand/plus/server/MetaTileFileSystemCache.java b/OsmAnd/src/net/osmand/plus/server/MetaTileFileSystemCache.java deleted file mode 100644 index 7da3315a0c..0000000000 --- a/OsmAnd/src/net/osmand/plus/server/MetaTileFileSystemCache.java +++ /dev/null @@ -1,96 +0,0 @@ -package net.osmand.plus.server; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import net.osmand.PlatformUtil; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.server.endpoints.TileEndpoint; -import org.apache.commons.logging.Log; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.concurrent.ConcurrentLinkedQueue; - -public class MetaTileFileSystemCache { - private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class); - private static final String TILES_FOLDER = "webtiles"; - private static final int MAX_IN_MEMORY_CACHE_SIZE = 16; - private static final int MAX_CACHE_SIZE = 64; - private final ConcurrentLinkedQueue inMemoryCache = new ConcurrentLinkedQueue<>(); - private final File externalCacheDir; - public boolean inMemoryCacheEnabled = true; - - public MetaTileFileSystemCache(OsmandApplication application) { - externalCacheDir = application.getAppPath(TILES_FOLDER); - if (!externalCacheDir.exists()) { - externalCacheDir.mkdir(); - } - } - - public void put(TileEndpoint.MetaTileCache tile) { - while (inMemoryCache.size() > MAX_IN_MEMORY_CACHE_SIZE) { - inMemoryCache.poll(); - } - // TODO list files too slow, better to have local variable to monitor or local list - while (externalCacheDir.listFiles().length > MAX_CACHE_SIZE) { - - for (int i = 0; i < externalCacheDir.listFiles().length - MAX_CACHE_SIZE; i++) { - externalCacheDir.listFiles()[i].delete(); - } - } - String fileName = tile.getTileId(); - File file = new File(externalCacheDir, fileName); - if (file.exists()) { - file.delete(); - } - try { - FileOutputStream out = new FileOutputStream(file); - tile.getBitmap().compress(Bitmap.CompressFormat.PNG, 100, out); - out.flush(); - out.close(); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - if (inMemoryCacheEnabled) { - inMemoryCache.add(tile); - } - } - - public TileEndpoint.MetaTileCache get(int zoom, int metaTileSize, int x, int y) { - int mx = (x / metaTileSize) * metaTileSize; - int my = (y / metaTileSize) * metaTileSize; - if (inMemoryCacheEnabled) { - for (TileEndpoint.MetaTileCache r : inMemoryCache) { - if (r.getZoom() == zoom && r.getEx() >= x && r.getEy() >= y && r.getSx() <= x && r.getSy() <= y) { - return r; - } - } - } - File file = new File(externalCacheDir, zoom + "_" + metaTileSize + "_" + mx + "_" + my); - if (file.exists()) { - TileEndpoint.MetaTileCache tile = new TileEndpoint.MetaTileCache( - BitmapFactory.decodeFile(file.getAbsolutePath()), - mx, my, mx + metaTileSize - 1, my + metaTileSize - 1, zoom); - if (inMemoryCacheEnabled) { - inMemoryCache.add(tile); - } - return tile; - } - return null; - } - - public void clearCache() { - clearInMemoryCache(); - clearFileCache(); - } - - private void clearFileCache() { - for (int i = 0; i < externalCacheDir.listFiles().length; i++) { - externalCacheDir.listFiles()[i].delete(); - } - } - - private void clearInMemoryCache() { - inMemoryCache.clear(); - } -} diff --git a/OsmAnd/src/net/osmand/plus/server/endpoints/MetaTileFileSystemCache.java b/OsmAnd/src/net/osmand/plus/server/endpoints/MetaTileFileSystemCache.java new file mode 100644 index 0000000000..b775531361 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/server/endpoints/MetaTileFileSystemCache.java @@ -0,0 +1,163 @@ +package net.osmand.plus.server.endpoints; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import net.osmand.PlatformUtil; +import net.osmand.data.RotatedTileBox; +import net.osmand.plus.OsmandApplication; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class MetaTileFileSystemCache { + private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class); + private static final String TILES_FOLDER = "webtiles"; + static final int TILE_SIZE_PX = 256; + static final int TILE_DENSITY = 2; + static final int METATILE_SIZE = 4; + private static final int MAX_IN_MEMORY_CACHE_SIZE = 16 / METATILE_SIZE; + private static final int MAX_CACHE_SIZE = 128; + + private final ConcurrentLinkedQueue inMemoryCache = new ConcurrentLinkedQueue<>(); + private final File externalCacheDir; + + public MetaTileFileSystemCache(OsmandApplication application) { + externalCacheDir = application.getAppPath(TILES_FOLDER); + if (!externalCacheDir.exists()) { + externalCacheDir.mkdir(); + } + } + + public void put(MetaTileCache tile) { + // TODO list files too slow, better to have local variable to monitor or local list + while (externalCacheDir.listFiles().length > MAX_CACHE_SIZE) { + for (int i = 0; i < externalCacheDir.listFiles().length - MAX_CACHE_SIZE; i++) { + externalCacheDir.listFiles()[i].delete(); + } + } + String fileName = tile.getTileId(); + File file = new File(externalCacheDir, fileName); + if (file.exists()) { + file.delete(); + } + try { + FileOutputStream out = new FileOutputStream(file); + tile.bmp.compress(Bitmap.CompressFormat.PNG, 100, out); + out.flush(); + out.close(); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + if (reserveMemSlot()) { + inMemoryCache.add(tile); + } + } + + private boolean reserveMemSlot() { + while (MAX_IN_MEMORY_CACHE_SIZE > 0 && inMemoryCache.size() >= MAX_IN_MEMORY_CACHE_SIZE) { + inMemoryCache.poll(); + } + return MAX_IN_MEMORY_CACHE_SIZE > 0; + } + + public MetaTileCache get(int zoom, int x, int y) { + int mx = (x / METATILE_SIZE) * METATILE_SIZE; + int my = (y / METATILE_SIZE) * METATILE_SIZE; + for (MetaTileCache r : inMemoryCache) { + if (r.zoom == zoom && r.ex >= x && r.ey >= y && r.sx <= x && r.sy <= y) { + return r; + } + } + File file = new File(externalCacheDir, zoom + "_" + METATILE_SIZE + "_" + mx + "_" + my); + if (file.exists()) { + MetaTileCache tile = new MetaTileCache( + BitmapFactory.decodeFile(file.getAbsolutePath()), + mx, my, mx + METATILE_SIZE - 1, my + METATILE_SIZE - 1, zoom); + if (reserveMemSlot()) { + inMemoryCache.add(tile); + } + return tile; + } + return null; + } + + public void clearCache() { + clearInMemoryCache(); + clearFileCache(); + } + + private void clearFileCache() { + for (int i = 0; i < externalCacheDir.listFiles().length; i++) { + externalCacheDir.listFiles()[i].delete(); + } + } + + private void clearInMemoryCache() { + inMemoryCache.clear(); + } + + public MetaTileCache createMetaTile(int zoom, int x, int y) { + int mx = (x / METATILE_SIZE) * METATILE_SIZE; + int my = (y / METATILE_SIZE) * METATILE_SIZE; + double lat = MapUtils.getLatitudeFromTile(zoom, my + 0.5 * METATILE_SIZE); + double lon = MapUtils.getLongitudeFromTile(zoom, mx + 0.5 * METATILE_SIZE); + MetaTileCache res = new MetaTileCache(); + res.bbox = new RotatedTileBox.RotatedTileBoxBuilder() + .setLocation(lat, lon) + .setMapDensity(TILE_DENSITY).density(TILE_DENSITY) + .setZoom(zoom) + .setPixelDimensions(TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, + TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, 0.5f, 0.5f).build(); + res.sx = mx; + res.ex = mx + METATILE_SIZE - 1; + res.sy = my; + res.ey = my + METATILE_SIZE - 1; + res.zoom = zoom; + return res; + } + + + public static class MetaTileCache { + Bitmap bmp; + int sx; + int sy; + int ex; + int ey; + int zoom; + public RotatedTileBox bbox; + + public MetaTileCache() { + + } + + public MetaTileCache(Bitmap bmp, int sx, int sy, int ex, int ey, int zoom) { + this.bmp = bmp; + this.sx = sx; + this.sy = sy; + this.ex = ex; + this.ey = ey; + this.zoom = zoom; + } + + // to be used in file name + public String getTileId() { + return zoom + "_" + METATILE_SIZE + "_" + sx + "_" + sy; + } + + public Bitmap getBitmap() { + return bmp; + } + + public Bitmap getSubtile(int x, int y) { + return Bitmap.createBitmap(bmp, + (x - sx) * TILE_SIZE_PX * TILE_DENSITY, + (y - sy) * TILE_SIZE_PX * TILE_DENSITY, + TILE_SIZE_PX * TILE_DENSITY, TILE_SIZE_PX * TILE_DENSITY); + } + } + +} diff --git a/OsmAnd/src/net/osmand/plus/server/endpoints/TileEndpoint.java b/OsmAnd/src/net/osmand/plus/server/endpoints/TileEndpoint.java index 91a054df17..92746ab301 100644 --- a/OsmAnd/src/net/osmand/plus/server/endpoints/TileEndpoint.java +++ b/OsmAnd/src/net/osmand/plus/server/endpoints/TileEndpoint.java @@ -6,7 +6,6 @@ import net.osmand.PlatformUtil; import net.osmand.data.RotatedTileBox; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.resources.AsyncLoadingThread; -import net.osmand.plus.server.MetaTileFileSystemCache; import net.osmand.plus.server.OsmAndHttpServer; import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; @@ -17,96 +16,16 @@ import java.io.ByteArrayOutputStream; import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse; public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint { - private static final int TILE_SIZE_PX = 256; - private static final int TILE_DENSITY = 2; + private static final int TIMEOUT_STEP = 500; private static final int TIMEOUT = 10000; - private static final int METATILE_SIZE = 2; + private static final Log LOG = PlatformUtil.getLog(TileEndpoint.class); private final MapActivity mapActivity; private final MetaTileFileSystemCache cache; private final RotatedTileBox mapTileBoxCopy; - public static class MetaTileCache { - Bitmap bmp; - int sx; - - public int getSx() { - return sx; - } - - public void setSx(int sx) { - this.sx = sx; - } - - public int getSy() { - return sy; - } - - public void setSy(int sy) { - this.sy = sy; - } - - public int getEx() { - return ex; - } - - public void setEx(int ex) { - this.ex = ex; - } - - public int getEy() { - return ey; - } - - public void setEy(int ey) { - this.ey = ey; - } - - public int getZoom() { - return zoom; - } - - public void setZoom(int zoom) { - this.zoom = zoom; - } - - int sy; - int ex; - int ey; - int zoom; - - public MetaTileCache() { - - } - - public MetaTileCache(Bitmap bmp, int sx, int sy, int ex, int ey, int zoom) { - this.bmp = bmp; - this.sx = sx; - this.sy = sy; - this.ex = ex; - this.ey = ey; - this.zoom = zoom; - } - - // to be used in file name - public String getTileId() { - return zoom + "_" + METATILE_SIZE + "_" + sx + "_" + sy; - } - - public Bitmap getBitmap() { - return bmp; - } - - public Bitmap getSubtile(int x, int y) { - return Bitmap.createBitmap(bmp, - (x - sx) * TILE_SIZE_PX * TILE_DENSITY, - (y - sy) * TILE_SIZE_PX * TILE_DENSITY, - TILE_SIZE_PX * TILE_DENSITY, TILE_SIZE_PX * TILE_DENSITY); - } - } - public TileEndpoint(MapActivity mapActivity) { this.mapActivity = mapActivity; this.cache = new MetaTileFileSystemCache(mapActivity.getMyApplication()); @@ -132,7 +51,7 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint { int zoom = Integer.parseInt(prms[1]); int x = Integer.parseInt(prms[2]); int y = Integer.parseInt(prms[3]); - MetaTileCache res = cache.get(zoom, METATILE_SIZE, x, y); + MetaTileFileSystemCache.MetaTileCache res = cache.get(zoom, x, y); if (res == null) { res = requestMetatile(x, y, zoom); if (res == null) { @@ -155,59 +74,34 @@ public class TileEndpoint implements OsmAndHttpServer.ApiEndpoint { str, str.available()); } - private synchronized MetaTileCache requestMetatile(int x, int y, int zoom) { - MetaTileCache cacheTile = this.cache.get(zoom, METATILE_SIZE, x, y); + private synchronized MetaTileFileSystemCache.MetaTileCache requestMetatile(int x, int y, int zoom) { + MetaTileFileSystemCache.MetaTileCache cacheTile = this.cache.get(zoom, x, y); if (cacheTile != null) { return cacheTile; } - int mx = (x / METATILE_SIZE) * METATILE_SIZE; - int my = (y / METATILE_SIZE) * METATILE_SIZE; - double lat = MapUtils.getLatitudeFromTile(zoom, my + 0.5 * METATILE_SIZE); - double lon = MapUtils.getLongitudeFromTile(zoom, mx + 0.5 * METATILE_SIZE); - final RotatedTileBox rotatedTileBox = new RotatedTileBox.RotatedTileBoxBuilder() - .setLocation(lat, lon) - .setMapDensity(TILE_DENSITY).density(TILE_DENSITY) - .setZoom(zoom) - .setPixelDimensions(TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, - TILE_SIZE_PX * TILE_DENSITY * METATILE_SIZE, 0.5f, 0.5f).build(); - mapActivity.getMapView().setCurrentViewport(rotatedTileBox); + + MetaTileFileSystemCache.MetaTileCache res = cache.createMetaTile(zoom, x, y); + mapActivity.getMapView().setCurrentViewport(res.bbox); int timeout = 0; try { AsyncLoadingThread athread = mapActivity.getMyApplication().getResourceManager().getAsyncLoadingThread(); Thread.sleep(TIMEOUT_STEP); // TODO line should be removed in future - MetaTileCache res = null; while (athread.areResourcesLoading() && timeout < TIMEOUT) { Thread.sleep(TIMEOUT_STEP); timeout += TIMEOUT_STEP; } + Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap(); if (timeout >= TIMEOUT) { - res = new MetaTileCache(); - res.sx = mx; - res.ex = mx + METATILE_SIZE - 1; - res.sy = my; - res.ey = my + METATILE_SIZE - 1; - res.zoom = zoom; - Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap(); Canvas canvas = new Canvas(tempBmp); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setTextSize(12); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); canvas.drawText("TIMEOUT", tempBmp.getWidth() / 2, tempBmp.getHeight() / 2, paint); - res.bmp = tempBmp.copy(tempBmp.getConfig(), true); - return res; - } - if (!athread.areResourcesLoading()) { - res = new MetaTileCache(); - res.sx = mx; - res.ex = mx + METATILE_SIZE - 1; - res.sy = my; - res.ey = my + METATILE_SIZE - 1; - res.zoom = zoom; - Bitmap tempBmp = mapActivity.getMapView().getBufferBitmap(); - res.bmp = tempBmp.copy(tempBmp.getConfig(), true); - this.cache.put(res); + // here we could return stub } + res.bmp = tempBmp.copy(tempBmp.getConfig(), true); + this.cache.put(res); return res; } catch (InterruptedException e) { LOG.error(e);