Index: trunk/src/org/openstreetmap/josm/data/ImageData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/ImageData.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/data/ImageData.java	(revision 16548)
@@ -5,4 +5,5 @@
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -18,5 +19,5 @@
  * @since 14590
  */
-public class ImageData {
+public class ImageData implements Data {
     /**
      * A listener that is informed when the current selection change
@@ -340,3 +341,8 @@
         listeners.removeListener(listener);
     }
+
+    @Override
+    public Collection<DataSource> getDataSources() {
+        return Collections.emptyList();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/NoteData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 16548)
@@ -10,4 +10,6 @@
 import java.util.Map;
 
+import org.openstreetmap.josm.data.Data;
+import org.openstreetmap.josm.data.DataSource;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.coor.LatLon;
@@ -21,5 +23,5 @@
  * Class to hold and perform operations on a set of notes
  */
-public class NoteData {
+public class NoteData implements Data {
 
     /**
@@ -310,3 +312,8 @@
         listeners.removeListener(listener);
     }
+
+    @Override
+    public Collection<DataSource> getDataSources() {
+        return Collections.emptyList(); // Notes don't currently store data sources
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java	(revision 16548)
@@ -2,4 +2,8 @@
 package org.openstreetmap.josm.gui.layer;
 
+import java.io.File;
+import java.io.IOException;
+
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.osm.Lockable;
 import org.openstreetmap.josm.gui.io.AbstractIOTask;
@@ -103,3 +107,27 @@
         return false;
     }
+
+    /**
+     * Perform the autosave action for the layer
+     *
+     * @param file The file to save to
+     * @return {@code true} if the layer was successfully saved
+     * @throws IOException If there was an IO exception from saving
+     * @since 16548
+     */
+    public boolean autosave(File file) throws IOException {
+        // Override if needed;
+        return false;
+    }
+
+    /**
+     * Get the data for the modifiable layer
+     *
+     * @return The data object
+     * @since 16548
+     */
+    public Data getData() {
+        // Override if needed;
+        return null;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java	(revision 16548)
@@ -32,5 +32,5 @@
 
 import org.openstreetmap.josm.actions.OpenFileAction.OpenFileTask;
-import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.osm.NoteData;
 import org.openstreetmap.josm.data.osm.NoteData.NoteDataUpdateListener;
@@ -42,7 +42,5 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.Notification;
-import org.openstreetmap.josm.gui.io.importexport.NoteExporter;
 import org.openstreetmap.josm.gui.io.importexport.NoteImporter;
-import org.openstreetmap.josm.gui.io.importexport.OsmExporter;
 import org.openstreetmap.josm.gui.io.importexport.OsmImporter;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
@@ -117,6 +115,5 @@
 
     private final DataSetListenerAdapter datasetAdapter = new DataSetListenerAdapter(this);
-    private final Set<DataSet> changedDatasets = new HashSet<>();
-    private final Set<NoteData> changedNoteData = new HashSet<>();
+    private final Set<Data> changedData = new HashSet<>();
     private final List<AutosaveLayerInfo<?>> layersInfo = new ArrayList<>();
     private final Object layersLock = new Object();
@@ -230,21 +227,10 @@
         }
         try {
-            if (info.layer instanceof OsmDataLayer) {
-                OsmDataLayer dataLayer = (OsmDataLayer) info.layer;
-                if (changedDatasets.remove(dataLayer.data)) {
-                    File file = getNewLayerFile(info, new Date(), 0);
-                    if (file != null) {
-                        info.backupFiles.add(file);
-                        new OsmExporter().exportData(file, info.layer, true /* no backup with appended ~ */);
-                    }
-                }
-            } else if (info.layer instanceof NoteLayer) {
-                NoteLayer noteLayer = (NoteLayer) info.layer;
-                if (changedNoteData.remove(noteLayer.getNoteData())) {
-                    File file = getNewLayerFile(info, new Date(), 0);
-                    if (file != null) {
-                        info.backupFiles.add(file);
-                        new NoteExporter().exportData(file, info.layer);
-                    }
+            Data data = info.layer.getData();
+            if (data != null && changedData.remove(data)) {
+                File file = getNewLayerFile(info, new Date(), 0);
+                if (file != null) {
+                    info.backupFiles.add(file);
+                    info.layer.autosave(file);
                 }
             }
@@ -267,6 +253,5 @@
                     savelayer(info);
                 }
-                changedDatasets.clear();
-                changedNoteData.clear();
+                changedData.clear();
                 if (PROP_NOTIFICATION.get() && !layersInfo.isEmpty()) {
                     GuiHelper.runInEDT(this::displayNotification);
@@ -311,4 +296,8 @@
         } else if (e.getAddedLayer() instanceof NoteLayer) {
             registerNewlayer((NoteLayer) e.getAddedLayer());
+        } else if (e.getAddedLayer() instanceof AbstractModifiableLayer) {
+            synchronized (layersLock) {
+                layersInfo.add(new AutosaveLayerInfo<>((AbstractModifiableLayer) e.getAddedLayer()));
+            }
         }
     }
@@ -355,10 +344,21 @@
     @Override
     public void processDatasetEvent(AbstractDatasetChangedEvent event) {
-        changedDatasets.add(event.getDataset());
+        dataUpdated(event.getDataset());
     }
 
     @Override
     public void noteDataUpdated(NoteData data) {
-        changedNoteData.add(data);
+        dataUpdated(data);
+    }
+
+    /**
+     * Indicate that data has changed, and it might be a good idea to autosave.
+     *
+     * @param data The data that has changed
+     * @return See {@link Set#add}
+     * @since 16548
+     */
+    public boolean dataUpdated(Data data) {
+        return changedData.add(data);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 16548)
@@ -28,4 +28,5 @@
 import org.openstreetmap.josm.actions.SaveActionBase;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.gpx.GpxConstants;
@@ -547,3 +548,8 @@
         return isLocalFile ? "survey" : null;
     }
+
+    @Override
+    public Data getData() {
+        return data;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/NoteLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/NoteLayer.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/NoteLayer.java	(revision 16548)
@@ -14,4 +14,5 @@
 import java.awt.event.MouseWheelListener;
 import java.io.File;
+import java.io.IOException;
 import java.text.DateFormat;
 import java.util.ArrayList;
@@ -36,4 +37,5 @@
 import org.openstreetmap.josm.actions.SaveActionBase;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.notes.Note;
 import org.openstreetmap.josm.data.notes.Note.State;
@@ -479,3 +481,14 @@
         return "Notes";
     }
+
+    @Override
+    public boolean autosave(File file) throws IOException {
+        new NoteExporter().exportData(file, this);
+        return true;
+    }
+
+    @Override
+    public Data getData() {
+        return getNoteData();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 16548)
@@ -55,4 +55,5 @@
 import org.openstreetmap.josm.data.APIDataSet;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.UndoRedoHandler;
@@ -112,4 +113,5 @@
 import org.openstreetmap.josm.gui.io.UploadLayerTask;
 import org.openstreetmap.josm.gui.io.importexport.NoteExporter;
+import org.openstreetmap.josm.gui.io.importexport.OsmExporter;
 import org.openstreetmap.josm.gui.io.importexport.OsmImporter;
 import org.openstreetmap.josm.gui.io.importexport.ValidatorErrorExporter;
@@ -1302,3 +1304,14 @@
         return isUploadInProgress.get();
     }
+
+    @Override
+    public Data getData() {
+        return getDataSet();
+    }
+
+    @Override
+    public boolean autosave(File file) throws IOException {
+        new OsmExporter().exportData(file, this, true /* no backup with appended ~ */);
+        return true;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 16546)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 16548)
@@ -41,4 +41,5 @@
 import org.openstreetmap.josm.actions.mapmode.SelectAction;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Data;
 import org.openstreetmap.josm.data.ImageData;
 import org.openstreetmap.josm.data.ImageData.ImageDataUpdateListener;
@@ -1009,3 +1010,8 @@
         return "Geotagged Images";
     }
+
+    @Override
+    public Data getData() {
+        return data;
+    }
 }
