diff --git a/documentation/docs/help/en/Advanced preferences.md b/documentation/docs/help/en/Advanced preferences.md
index 1d96294b40..363461daaa 100644
--- a/documentation/docs/help/en/Advanced preferences.md	
+++ b/documentation/docs/help/en/Advanced preferences.md	
@@ -395,7 +395,7 @@ Enable voice command support: Default: _off_.
 
 ### Enable hardware acceleration
 
-Do not use, may cause hangs of the app and other problems.
+Turn on use of hardware rendering on Android 10 and later. Default: _off_
 
 ### Enable split window property editor
 
diff --git a/src/main/assets/help/en/Advanced preferences.html b/src/main/assets/help/en/Advanced preferences.html
index 21cd991d05..9b88d8131e 100644
--- a/src/main/assets/help/en/Advanced preferences.html	
+++ b/src/main/assets/help/en/Advanced preferences.html	
@@ -203,7 +203,7 @@ <h3>Enable JS Console</h3>
 <h3>Enable voice commands</h3>
 <p>Enable voice command support: Default: <em>off</em>.</p>
 <h3>Enable hardware acceleration</h3>
-<p>Do not use, may cause hangs of the app and other problems.</p>
+<p>Turn on use of hardware rendering on Android 10 and later. Default: <em>off</em></p>
 <h3>Enable split window property editor</h3>
 <p>Enable displaying the property editor in a separate window if available. Default: <em>off</em></p>
 <h3>Use &quot;new task&quot; mode for property editor</h3>
diff --git a/src/main/assets/styles/Color-round-no-mp.xml b/src/main/assets/styles/Color-round-no-mp.xml
index 645aed1cf3..916a1ace46 100644
--- a/src/main/assets/styles/Color-round-no-mp.xml
+++ b/src/main/assets/styles/Color-round-no-mp.xml
@@ -32,7 +32,7 @@
         </dash>
     </feature>
     <!-- Validation -->
-    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" />
+    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" />
     <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" />
     <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" />
     <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" />
diff --git a/src/main/assets/styles/Color-round.xml b/src/main/assets/styles/Color-round.xml
index dcab5ac43d..20a64acac0 100644
--- a/src/main/assets/styles/Color-round.xml
+++ b/src/main/assets/styles/Color-round.xml
@@ -32,7 +32,7 @@
         </dash>
     </feature>
     <!-- Validation -->
-    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" />
+    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" />
     <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" />
     <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" />
     <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" />
diff --git a/src/main/assets/styles/No-path-patterns.xml b/src/main/assets/styles/No-path-patterns.xml
index 701d91067a..ce14f25945 100644
--- a/src/main/assets/styles/No-path-patterns.xml
+++ b/src/main/assets/styles/No-path-patterns.xml
@@ -32,7 +32,7 @@
         </dash>
     </feature>
     <!-- Validation -->
-    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" />
+    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" />
     <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" />
     <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" />
     <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" />
diff --git a/src/main/assets/styles/Pen-round.xml b/src/main/assets/styles/Pen-round.xml
index 93b8d2d35d..dcde98b697 100644
--- a/src/main/assets/styles/Pen-round.xml
+++ b/src/main/assets/styles/Pen-round.xml
@@ -32,7 +32,7 @@
         </dash>
     </feature>
     <!-- Validation -->
-    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" />
+    <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" />
     <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" />
     <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" />
     <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" />
diff --git a/src/main/java/de/blau/android/Map.java b/src/main/java/de/blau/android/Map.java
index c031fc93a4..1c99e1b4bb 100755
--- a/src/main/java/de/blau/android/Map.java
+++ b/src/main/java/de/blau/android/Map.java
@@ -172,6 +172,8 @@ public class Map extends View implements IMapView {
 
     private TrackerService tracker = null;
 
+    private final boolean hardwareLayerType;
+
     /**
      * Construct a new Map object that orchestrates the layer drawing and related rendering
      * 
@@ -192,7 +194,8 @@ public Map(@NonNull final Context context) {
 
         iconRadius = Density.dpToPx(context, ICON_SIZE_DP / 2);
 
-        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        hardwareLayerType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && App.getPreferences(context).hwAccelerationEnabled();
+        setLayerType(hardwareLayerType ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_SOFTWARE, null);
     }
 
     /**
@@ -225,7 +228,7 @@ public void setUpLayers(@NonNull Context ctx) {
                                     layer = new de.blau.android.layer.mvt.MapOverlay(this, new VectorTileRenderer(), false);
                                     ((MapTilesOverlayLayer<?>) layer).setRendererInfo(backgroundSource);
                                 } else {
-                                    layer = new MapTilesLayer<Bitmap>(this, backgroundSource, null, new MapTilesLayer.BitmapTileRenderer());
+                                    layer = new MapTilesLayer<Bitmap>(this, backgroundSource, null, new MapTilesLayer.BitmapTileRenderer(hardwareLayerType));
                                 }
                             }
                             break;
@@ -235,7 +238,7 @@ public void setUpLayers(@NonNull Context ctx) {
                                 if (overlaySource.getTileType() == TileType.MVT) {
                                     layer = new de.blau.android.layer.mvt.MapOverlay(this, new VectorTileRenderer(), true);
                                 } else {
-                                    layer = new MapTilesOverlayLayer<Bitmap>(this, new MapTilesLayer.BitmapTileRenderer());
+                                    layer = new MapTilesOverlayLayer<Bitmap>(this, new MapTilesLayer.BitmapTileRenderer(hardwareLayerType));
                                 }
                                 ((MapTilesOverlayLayer<?>) layer).setRendererInfo(overlaySource);
                             }
@@ -1302,4 +1305,15 @@ public TrackerService getTracker() {
     public boolean rtlLayout() {
         return getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
     }
+
+    /**
+     * Check if we configured hardware acceleration
+     * 
+     * The value returned from isHardwareAccelerated seems to not necessarily be consistent with what we set
+     * 
+     * @return true if we enabled hardware acceleration
+     */
+    public boolean isHardwareLayerType() {
+        return hardwareLayerType;
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java b/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java
index 6ae319fa31..6a424f6133 100644
--- a/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java
+++ b/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java
@@ -153,7 +153,7 @@ protected Void doInBackground(Void param) {
                     text.setText(tester.getOutput());
                     byte[] image = tester.getTile();
                     if (result && tester.getTileType() == TileType.BITMAP && image != null && image.length > 0) {
-                        BitmapDecoder decoder = new BitmapDecoder();
+                        BitmapDecoder decoder = new BitmapDecoder(false);
                         Bitmap bitmap = decoder.decode(image, false);
                         if (bitmap != null) {
                             tileView.setVisibility(View.VISIBLE);
diff --git a/src/main/java/de/blau/android/layer/data/MapOverlay.java b/src/main/java/de/blau/android/layer/data/MapOverlay.java
index 17555005e8..f020f28014 100644
--- a/src/main/java/de/blau/android/layer/data/MapOverlay.java
+++ b/src/main/java/de/blau/android/layer/data/MapOverlay.java
@@ -478,7 +478,7 @@ protected void onDraw(Canvas canvas, IMapView osmv) {
     @SuppressWarnings("unchecked")
     private void paintOsmData(@NonNull final Canvas canvas) {
 
-        boolean hwAccelarationWorkaround = canvas.isHardwareAccelerated();
+        boolean hwAccelerated = canvas.isHardwareAccelerated();
 
         int screenWidth = map.getWidth();
         int screenHeight = map.getHeight();
@@ -607,8 +607,7 @@ private void paintOsmData(@NonNull final Canvas canvas) {
                     coordSize++;
                 }
             }
-            paintNode(canvas, n, x, y, hwAccelarationWorkaround,
-                    drawTolerance && !noTolerance && (n.getState() != OsmElement.STATE_UNCHANGED || isInDownload(lon, lat)));
+            paintNode(canvas, n, x, y, hwAccelerated, drawTolerance && !noTolerance && (n.getState() != OsmElement.STATE_UNCHANGED || isInDownload(lon, lat)));
         }
         // turn restrictions
         if (inNodeIconZoomRange && showIcons) {
@@ -977,10 +976,10 @@ private void paintRestriction(@NonNull final Canvas canvas, int screenWidth, int
      * @param node Node to be painted.
      * @param x screen x coordinate
      * @param y screen y coordinate
-     * @param hwAccelarationWorkaround use a workaround for unsupported operations when HW acceleration is used
+     * @param hwAccelerated use a workaround for unsupported operations when HW acceleration is used
      * @param drawTolerance draw the touch halo
      */
-    private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, final float x, final float y, final boolean hwAccelarationWorkaround,
+    private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, final float x, final float y, final boolean hwAccelerated,
             final boolean drawTolerance) {
 
         boolean isSelected = tmpDrawingSelectedNodes != null && tmpDrawingSelectedNodes.contains(node);
@@ -1068,57 +1067,58 @@ private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, f
             isTagged = false;
         }
 
-        if (isTagged) {
-            boolean noIcon = true;
-            if (inNodeIconZoomRange && showIcons) {
-                Float direction = getDirection(node);
-                if (direction != null && !direction.equals(Float.NaN)) {
-                    canvas.save();
-                    canvas.rotate(direction + 90, x, y);
-                    canvas.translate(x - iconRadius, y);
-                    canvas.drawPath(currentStyle.getDirectionArrowPath(), nodeFeatureStyle.getPaint());
-                    canvas.restore();
-                }
+        if (!isTagged) {
+            // this bit of code duplication makes sense
+            if (zoomLevel < featureStyle.getMinVisibleZoom()) {
+                return;
+            }
+            Paint paint = featureStyle.getPaint();
+            if (hwAccelerated) { // we don't actually know if this is slower than drawPoint
+                canvas.drawCircle(x, y, paint.getStrokeWidth() / 2, paint);
+            } else {
+                canvas.drawPoint(x, y, paint);
+            }
+            return;
+        }
 
-                noIcon = tmpPresets == null || !paintNodeIcon(node, canvas, x, y, isSelected || hasProblem ? featureStyleTagged : null);
-                if (noIcon) {
-                    String houseNumber = node.getTagWithKey(Tags.KEY_ADDR_HOUSENUMBER);
-                    if (houseNumber != null && !"".equals(houseNumber)) { // draw house-numbers
-                        paintHouseNumber(x, y, canvas, featureStyleThin, featureStyleFontSmall, houseNumber);
-                        return;
-                    }
-                } else if (zoomLevel > showIconLabelZoomLimit) {
-                    paintLabel(x, y, canvas, featureStyleFont, node, nodeFeatureStyleTagged.getPaint().getStrokeWidth(), true);
-                }
+        boolean noIcon = true;
+        if (inNodeIconZoomRange && showIcons) {
+            Float direction = getDirection(node);
+            if (direction != null && !direction.equals(Float.NaN)) {
+                canvas.save();
+                canvas.rotate(direction + 90, x, y);
+                canvas.translate(x - iconRadius, y);
+                canvas.drawPath(currentStyle.getDirectionArrowPath(), nodeFeatureStyle.getPaint());
+                canvas.restore();
             }
 
+            noIcon = tmpPresets == null || !paintNodeIcon(node, canvas, x, y, isSelected || hasProblem ? featureStyleTagged : null);
             if (noIcon) {
-                // draw regular nodes or without icons
-                if (zoomLevel < featureStyleTagged.getMinVisibleZoom()) {
+                String houseNumber = node.getTagWithKey(Tags.KEY_ADDR_HOUSENUMBER);
+                if (houseNumber != null && !"".equals(houseNumber)) { // draw house-numbers
+                    paintHouseNumber(x, y, canvas, featureStyleThin, featureStyleFontSmall, houseNumber);
                     return;
                 }
-                Paint paint = featureStyleTagged.getPaint();
-                float strokeWidth = paint.getStrokeWidth();
-                if (hwAccelarationWorkaround) {
-                    canvas.drawCircle(x, y, strokeWidth / 2, paint);
-                } else {
-                    canvas.drawPoint(x, y, paint);
-                }
-                if (inNodeIconZoomRange) {
-                    paintLabel(x, y, canvas, featureStyleFont, node, strokeWidth, false);
-                }
+            } else if (zoomLevel > showIconLabelZoomLimit) {
+                paintLabel(x, y, canvas, featureStyleFont, node, nodeFeatureStyleTagged.getPaint().getStrokeWidth(), true);
             }
-        } else {
-            // this bit of code duplication makes sense
-            if (zoomLevel < featureStyle.getMinVisibleZoom()) {
+        }
+
+        if (noIcon) {
+            // draw regular nodes or without icons
+            if (zoomLevel < featureStyleTagged.getMinVisibleZoom()) {
                 return;
             }
-            Paint paint = featureStyle.getPaint();
-            if (hwAccelarationWorkaround) { // FIXME we don't actually know if this is slower than drawPoint
-                canvas.drawCircle(x, y, paint.getStrokeWidth() / 2, paint);
+            Paint paint = featureStyleTagged.getPaint();
+            float strokeWidth = paint.getStrokeWidth();
+            if (hwAccelerated) {
+                canvas.drawCircle(x, y, strokeWidth / 2, paint);
             } else {
                 canvas.drawPoint(x, y, paint);
             }
+            if (inNodeIconZoomRange) {
+                paintLabel(x, y, canvas, featureStyleFont, node, strokeWidth, false);
+            }
         }
     }
 
@@ -1271,8 +1271,13 @@ private void retrieveIcon(@NonNull OsmElement element, boolean isWay, @NonNull W
         }
         Bitmap icon;
         if (iconDrawable != null) {
-            icon = Bitmap.createBitmap(iconRadius * 2, iconRadius * 2, Config.ARGB_8888);
+            icon = Bitmap.createBitmap(iconRadius * 2, iconRadius * 2, Bitmap.Config.ARGB_8888);
             iconDrawable.draw(new Canvas(icon));
+            if (map.isHardwareLayerType()) {
+                Bitmap temp = icon;
+                icon = temp.copy(Bitmap.Config.HARDWARE, false);
+                temp.recycle();
+            }
         } else {
             icon = NOICON;
         }
diff --git a/src/main/java/de/blau/android/layer/tasks/MapOverlay.java b/src/main/java/de/blau/android/layer/tasks/MapOverlay.java
index e481ab3e31..61ff5e62c4 100644
--- a/src/main/java/de/blau/android/layer/tasks/MapOverlay.java
+++ b/src/main/java/de/blau/android/layer/tasks/MapOverlay.java
@@ -1,5 +1,7 @@
 package de.blau.android.layer.tasks;
 
+import static de.blau.android.contract.Constants.LOG_TAG_LEN;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -59,7 +61,8 @@
 public class MapOverlay extends MapViewLayer
         implements ExtentInterface, DiscardInterface, ClickableInterface<Task>, LayerInfoInterface, ConfigureInterface, PruneableInterface {
 
-    private static final String DEBUG_TAG = MapOverlay.class.getSimpleName().substring(0, Math.min(23, MapOverlay.class.getSimpleName().length()));
+    private static final int    TAG_LEN   = Math.min(LOG_TAG_LEN, MapOverlay.class.getSimpleName().length());
+    private static final String DEBUG_TAG = MapOverlay.class.getSimpleName().substring(0, TAG_LEN);
 
     public static final String FILENAME = "selectedtask" + "." + FileExtensions.RES;
 
@@ -120,10 +123,11 @@ public MapOverlay(@NonNull final Map map) {
         setPrefs(prefs);
         download = new TaskDownloader(prefs.getServer());
         // the following sets up the static icon caches
-        Note.setupIconCache(context);
-        OsmoseBug.setupIconCache(context);
-        MapRouletteTask.setupIconCache(context);
-        Todo.setupIconCache(context);
+        boolean hwAccelerated = map.isHardwareLayerType();
+        Note.setupIconCache(context, hwAccelerated);
+        OsmoseBug.setupIconCache(context, hwAccelerated);
+        MapRouletteTask.setupIconCache(context, hwAccelerated);
+        Todo.setupIconCache(context, hwAccelerated);
     }
 
     @Override
diff --git a/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java b/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java
index 5f8225ccce..0c7abd3012 100644
--- a/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java
+++ b/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java
@@ -1,5 +1,7 @@
 package de.blau.android.prefs;
 
+import static de.blau.android.contract.Constants.LOG_TAG_LEN;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -21,7 +23,8 @@
 
 public class AdvancedPrefEditorFragment extends ExtendedPreferenceFragment {
 
-    private static final String DEBUG_TAG = AdvancedPrefEditorFragment.class.getSimpleName().substring(0, Math.min(23, AdvancedPrefEditorFragment.class.getSimpleName().length()));
+    private static final int    TAG_LEN   = Math.min(LOG_TAG_LEN, AdvancedPrefEditorFragment.class.getSimpleName().length());
+    private static final String DEBUG_TAG = AdvancedPrefEditorFragment.class.getSimpleName().substring(0, TAG_LEN);
 
     private Resources    r;
     AdvancedPrefDatabase db;
@@ -87,6 +90,7 @@ public void onResume() {
         setRestartRequiredMessage(R.string.config_autosaveMaxFiles_key);
         setRestartRequiredMessage(R.string.config_indexMediaStore_key);
         setRestartRequiredMessage(R.string.config_supportPresetLabels_key);
+        setRestartRequiredMessage(R.string.config_enableHwAcceleration_key);
         setTitle();
     }
 
diff --git a/src/main/java/de/blau/android/tasks/MapRouletteTask.java b/src/main/java/de/blau/android/tasks/MapRouletteTask.java
index 7e389c1d28..c113952c23 100644
--- a/src/main/java/de/blau/android/tasks/MapRouletteTask.java
+++ b/src/main/java/de/blau/android/tasks/MapRouletteTask.java
@@ -59,12 +59,15 @@ public class MapRouletteTask extends LongIdTask {
 
     /**
      * Setup the icon caches
+     * 
+     * @param context android Context
+     * @param hwAccelerated true if the Canvas is hw accelerated
      */
-    public static void setupIconCache(Context context) {
-        cachedIconRouletteOpen = getIcon(context, R.drawable.roulette_open);
-        cachedIconRouletteChanged = getIcon(context, R.drawable.roulette_changed);
-        cachedIconChangedRouletteClosed = getIcon(context, R.drawable.roulette_closed_changed);
-        cachedIconRouletteClosed = getIcon(context, R.drawable.roulette_closed);
+    public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) {
+        cachedIconRouletteOpen = getIcon(context, R.drawable.roulette_open, hwAccelerated);
+        cachedIconRouletteChanged = getIcon(context, R.drawable.roulette_changed, hwAccelerated);
+        cachedIconChangedRouletteClosed = getIcon(context, R.drawable.roulette_closed_changed, hwAccelerated);
+        cachedIconRouletteClosed = getIcon(context, R.drawable.roulette_closed, hwAccelerated);
     }
 
     @Override
diff --git a/src/main/java/de/blau/android/tasks/Note.java b/src/main/java/de/blau/android/tasks/Note.java
index 33978c0e22..6f34af2071 100644
--- a/src/main/java/de/blau/android/tasks/Note.java
+++ b/src/main/java/de/blau/android/tasks/Note.java
@@ -109,12 +109,15 @@ public Note(XmlPullParser parser) throws XmlPullParserException, IOException, Nu
 
     /**
      * Setup the icon caches
+     * 
+     * @param context android Context
+     * @param hwAccelerated true if the Canvas is hw accelerated
      */
-    public static void setupIconCache(Context context) {
-        cachedIconNoteOpen = getIcon(context, R.drawable.note_open);
-        cachedIconNoteChanged = getIcon(context, R.drawable.note_changed);
-        cachedIconNoteChangedClosed = getIcon(context, R.drawable.note_changed_closed);
-        cachedIconNoteClosed = getIcon(context, R.drawable.note_closed);
+    public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) {
+        cachedIconNoteOpen = getIcon(context, R.drawable.note_open, hwAccelerated);
+        cachedIconNoteChanged = getIcon(context, R.drawable.note_changed, hwAccelerated);
+        cachedIconNoteChangedClosed = getIcon(context, R.drawable.note_changed_closed, hwAccelerated);
+        cachedIconNoteClosed = getIcon(context, R.drawable.note_closed, hwAccelerated);
     }
 
     /**
diff --git a/src/main/java/de/blau/android/tasks/OsmoseBug.java b/src/main/java/de/blau/android/tasks/OsmoseBug.java
index f9a4e21b97..8ef023e42a 100644
--- a/src/main/java/de/blau/android/tasks/OsmoseBug.java
+++ b/src/main/java/de/blau/android/tasks/OsmoseBug.java
@@ -1,5 +1,7 @@
 package de.blau.android.tasks;
 
+import static de.blau.android.contract.Constants.LOG_TAG_LEN;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -27,7 +29,8 @@ public final class OsmoseBug extends Bug implements Serializable {
 
     private static final long serialVersionUID = 5L;
 
-    private static final String DEBUG_TAG = OsmoseBug.class.getSimpleName().substring(0, Math.min(23, OsmoseBug.class.getSimpleName().length()));
+    private static final int    TAG_LEN   = Math.min(LOG_TAG_LEN, OsmoseBug.class.getSimpleName().length());
+    private static final String DEBUG_TAG = OsmoseBug.class.getSimpleName().substring(0, TAG_LEN);
 
     private static final String OSMOSE_ISSUES   = "issues";
     private static final String OSMOSE_LAT      = "lat";
@@ -56,12 +59,15 @@ public final class OsmoseBug extends Bug implements Serializable {
 
     /**
      * Setup the icon caches
+     * 
+     * @param context android Context
+     * @param hwAccelerated true if the Canvas is hw accelerated
      */
-    public static void setupIconCache(Context context) {
-        cachedIconBugOpen = getIcon(context, R.drawable.bug_open);
-        cachedIconBugChanged = getIcon(context, R.drawable.bug_changed);
-        cachedIconChangedBugClosed = getIcon(context, R.drawable.bug_changed_closed);
-        cachedIconBugClosed = getIcon(context, R.drawable.bug_closed);
+    public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) {
+        cachedIconBugOpen = getIcon(context, R.drawable.bug_open, hwAccelerated);
+        cachedIconBugChanged = getIcon(context, R.drawable.bug_changed, hwAccelerated);
+        cachedIconChangedBugClosed = getIcon(context, R.drawable.bug_changed_closed, hwAccelerated);
+        cachedIconBugClosed = getIcon(context, R.drawable.bug_closed, hwAccelerated);
     }
 
     /**
diff --git a/src/main/java/de/blau/android/tasks/Task.java b/src/main/java/de/blau/android/tasks/Task.java
index 64422382f4..829fdec327 100644
--- a/src/main/java/de/blau/android/tasks/Task.java
+++ b/src/main/java/de/blau/android/tasks/Task.java
@@ -224,12 +224,15 @@ public void setChanged(boolean changed) {
      * 
      * @param context Android Context
      * @param icon the icon resource
+     * @param hwAccelerated true is the canvas is hw accellerated
      * @return the Bitmap
      */
     @NonNull
-    static BitmapWithOffset getIcon(@NonNull Context context, int icon) {
+    static BitmapWithOffset getIcon(@NonNull Context context, int icon, boolean hwAccelerated) {
         BitmapWithOffset bitmap = new BitmapWithOffset();
-        bitmap.icon = BitmapFactory.decodeResource(context.getResources(), icon);
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = hwAccelerated ? Bitmap.Config.HARDWARE : Bitmap.Config.ARGB_8888;
+        bitmap.icon = BitmapFactory.decodeResource(context.getResources(), icon, options);
         bitmap.w2 = bitmap.icon.getWidth() / 2f;
         bitmap.h2 = bitmap.icon.getHeight() / 2f;
         bitmap.iconSelectedBorder = Density.dpToPx(context, ICON_SELECTED_BORDER);
diff --git a/src/main/java/de/blau/android/tasks/Todo.java b/src/main/java/de/blau/android/tasks/Todo.java
index f0147f3bad..8340580ea3 100644
--- a/src/main/java/de/blau/android/tasks/Todo.java
+++ b/src/main/java/de/blau/android/tasks/Todo.java
@@ -67,12 +67,15 @@ public final class Todo extends Bug implements Serializable {
 
     /**
      * Setup the icon caches
+     * 
+     * @param context android Context
+     * @param hwAccelerated true if the Canvas is hw accelerated
      */
-    public static void setupIconCache(Context context) {
-        cachedIconTodoOpen = getIcon(context, R.drawable.todo_open);
-        cachedIconTogoChanged = getIcon(context, R.drawable.todo_open);
-        cachedIconTodoChangedClosed = getIcon(context, R.drawable.todo_closed);
-        cachedIconTodoClosed = getIcon(context, R.drawable.todo_closed);
+    public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) {
+        cachedIconTodoOpen = getIcon(context, R.drawable.todo_open, hwAccelerated);
+        cachedIconTogoChanged = getIcon(context, R.drawable.todo_open, hwAccelerated);
+        cachedIconTodoChangedClosed = getIcon(context, R.drawable.todo_closed, hwAccelerated);
+        cachedIconTodoClosed = getIcon(context, R.drawable.todo_closed, hwAccelerated);
     }
 
     /**
diff --git a/src/main/java/de/blau/android/views/layers/MapTilesLayer.java b/src/main/java/de/blau/android/views/layers/MapTilesLayer.java
index 5e44607614..cf62d4abf6 100644
--- a/src/main/java/de/blau/android/views/layers/MapTilesLayer.java
+++ b/src/main/java/de/blau/android/views/layers/MapTilesLayer.java
@@ -1,5 +1,7 @@
 package de.blau.android.views.layers;
 
+import static de.blau.android.contract.Constants.LOG_TAG_LEN;
+
 import java.io.IOException;
 import java.util.BitSet;
 import java.util.Collection;
@@ -68,7 +70,8 @@
  */
 public class MapTilesLayer<T> extends MapViewLayer implements ExtentInterface, LayerInfoInterface, DiscardInterface, AttributionInterface {
 
-    private static final String DEBUG_TAG = MapTilesLayer.class.getSimpleName().substring(0, Math.min(23, MapTilesLayer.class.getSimpleName().length()));
+    private static final int    TAG_LEN   = Math.min(LOG_TAG_LEN, MapTilesLayer.class.getSimpleName().length());
+    private static final String DEBUG_TAG = MapTilesLayer.class.getSimpleName().substring(0, TAG_LEN);
 
     /** Define a minimum active area for taps on the tile attribution data. */
     private static final int TAPAREA_MIN_WIDTH  = 40;
@@ -173,6 +176,16 @@ default void postRender(@NonNull Canvas c, int z) {
     }
 
     public static class BitmapTileRenderer implements TileRenderer<Bitmap> {
+        private final boolean hardwareRenderer;
+
+        /**
+         * Construct a new renderer
+         * 
+         * @param hardwareRenderer decode bitmap for hardware rendering if true
+         */
+        public BitmapTileRenderer(boolean hardwareRenderer) {
+            this.hardwareRenderer = hardwareRenderer;
+        }
 
         @Override
         public void render(@NonNull Canvas c, @NonNull Bitmap tileBlob, int z, @Nullable Rect fromRect, @NonNull Rect screenRect, @NonNull Paint paint) {
@@ -182,7 +195,7 @@ public void render(@NonNull Canvas c, @NonNull Bitmap tileBlob, int z, @Nullable
         @Override
         @NonNull
         public TileDecoder<Bitmap> decoder() {
-            return new MapTileProvider.BitmapDecoder();
+            return new MapTileProvider.BitmapDecoder(hardwareRenderer);
         }
     }
 
diff --git a/src/main/java/de/blau/android/views/util/MapTileProvider.java b/src/main/java/de/blau/android/views/util/MapTileProvider.java
index 7f2b63ca2f..7968ab6be2 100644
--- a/src/main/java/de/blau/android/views/util/MapTileProvider.java
+++ b/src/main/java/de/blau/android/views/util/MapTileProvider.java
@@ -1,5 +1,7 @@
 package de.blau.android.views.util;
 
+import static de.blau.android.contract.Constants.LOG_TAG_LEN;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -46,7 +48,8 @@ public class MapTileProvider<T> {
     /**
      * Tag used in debug log-entries.
      */
-    private static final String DEBUG_TAG = MapTileProvider.class.getSimpleName().substring(0, Math.min(23, MapTileProvider.class.getSimpleName().length()));
+    private static final int    TAG_LEN   = Math.min(LOG_TAG_LEN, MapTileProvider.class.getSimpleName().length());
+    private static final String DEBUG_TAG = MapTileProvider.class.getSimpleName().substring(0, TAG_LEN);
 
     private static final int MVT_CACHE_SIZE = 128;
 
@@ -85,17 +88,30 @@ public interface TileDecoder<D> {
     public static class BitmapDecoder implements TileDecoder<Bitmap> {
         private BitmapFactory.Options options = new BitmapFactory.Options();
 
+        private boolean hardwareRendering;
+
+        /**
+         * Construct a new decoder
+         * 
+         * @param hardwareRendering if true decode for hardware rendering
+         */
+        public BitmapDecoder(boolean hardwareRendering) {
+            this.hardwareRendering = hardwareRendering;
+        }
+
         @Override
         public Bitmap decode(@NonNull byte[] data, boolean small) {
-            if (small) {
+            if (hardwareRendering) {
+                options.inPreferredConfig = Bitmap.Config.HARDWARE;
+            } else if (small) {
                 options.inPreferredConfig = Bitmap.Config.RGB_565;
             } else {
                 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
             }
             return BitmapFactory.decodeByteArray(data, 0, data.length, options);
         }
-
     }
+
     // ===========================================================
     // Constructors
     // ===========================================================
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 30838ad88c..5c688dbc1c 100755
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -1314,7 +1314,7 @@
     <string name="config_enableAntiAliasing_title">Enable anti-aliasing</string>
     <string name="config_enableAntiAliasing_summary">Makes the lines smoother.</string>
     <string name="config_enableHwAcceleration_title">Enable hardware acceleration</string>
-    <string name="config_enableHwAcceleration_summary">Allows use of hardware acceleration if and where supported, currently setting this has no effect.</string>
+    <string name="config_enableHwAcceleration_summary">Turn on use of hardware rendering on Android 10 and later.</string>
     <string name="config_maxStrokeWidth_title">Max line width</string>
     <string name="config_maxStrokeWidth_summary">Do not draw a way thicker than this.</string>
     <string name="config_maxStrokeWidth_current">%1$d px</string>