Fix the overrides file corruption due to shutdown

The dynamic overrides file could be corrupted by shutdown during
writes. This CL introduces the backup file to avoid corruption.

Test: manual
   1. push a backup file to /data/misc/appcompat/
   2. push a corrupted file to /data/misc/appcompat/
   3. Reboot and see if it reads the backup file
Bug: 196909332
Change-Id: If13547f04a4712ab18dcb97ffee698327797f97b
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 2bf1ccd..fb74170 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -81,8 +81,11 @@
     private final OverrideValidatorImpl mOverrideValidator;
     private final AndroidBuildClassifier mAndroidBuildClassifier;
     private Context mContext;
-    @GuardedBy("mOverridesFile")
+    private final Object mOverridesFileLock = new Object();
+    @GuardedBy("mOverridesFileLock")
     private File mOverridesFile;
+    @GuardedBy("mOverridesFileLock")
+    private File mBackupOverridesFile;
 
     @VisibleForTesting
     CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
@@ -550,8 +553,15 @@
 
         loadOverrides(staticOverridesFile);
 
-        mOverridesFile = dynamicOverridesFile;
-        loadOverrides(dynamicOverridesFile);
+        synchronized (mOverridesFileLock) {
+            mOverridesFile = dynamicOverridesFile;
+            mBackupOverridesFile = makeBackupFile(dynamicOverridesFile);
+            if (mBackupOverridesFile.exists()) {
+                mOverridesFile.delete();
+                mBackupOverridesFile.renameTo(mOverridesFile);
+            }
+            loadOverrides(mOverridesFile);
+        }
 
         if (staticOverridesFile.exists()) {
             // Only save overrides if there is a static overrides file.
@@ -559,6 +569,10 @@
         }
     }
 
+    private File makeBackupFile(File overridesFile) {
+        return new File(overridesFile.getPath() + ".bak");
+    }
+
     private void loadOverrides(File overridesFile) {
         if (!overridesFile.exists()) {
             // Overrides file doesn't exist.
@@ -591,10 +605,11 @@
      * Persist compat framework overrides to /data/misc/appcompat/compat_framework_overrides.xml
      */
     void saveOverrides() {
-        if (mOverridesFile == null) {
-            return;
-        }
-        synchronized (mOverridesFile) {
+        synchronized (mOverridesFileLock) {
+            if (mOverridesFile == null || mBackupOverridesFile == null) {
+                return;
+            }
+
             Overrides overrides = new Overrides();
             List<ChangeOverrides> changeOverridesList = overrides.getChangeOverrides();
             for (CompatChange c : mChanges.values()) {
@@ -603,6 +618,20 @@
                     changeOverridesList.add(changeOverrides);
                 }
             }
+
+            // Rename the file to the backup.
+            if (mOverridesFile.exists()) {
+                if (mBackupOverridesFile.exists()) {
+                    mOverridesFile.delete();
+                } else {
+                    if (!mOverridesFile.renameTo(mBackupOverridesFile)) {
+                        Slog.e(TAG, "Couldn't rename file " + mOverridesFile
+                                + " to " + mBackupOverridesFile);
+                        return;
+                    }
+                }
+            }
+
             // Create the file if it doesn't already exist
             try {
                 mOverridesFile.createNewFile();
@@ -616,6 +645,9 @@
             } catch (IOException e) {
                 Slog.e(TAG, e.toString());
             }
+
+            // Remove the backup if the write succeeds.
+            mBackupOverridesFile.delete();
         }
     }