Persist settings on a dedicated background thread

Settings were persisted on the system background thread but during
first boot the device is under heavy load and persisting settings
competes with other system components using the shared background
thread. As a result persisting settings can be delayed much longer
than the expected 200ms. This can cause issues with setup wizard
being skipped/went over and its component disaabled being persisted
but the setting whether the device is provisioned not being
persisted - now if the device boots it will have no SUW but also
the home button would be missing. Generally, we need a tansactional
abstraction in the system process to peform all delayed operations
atomically.

bug:25472484

Change-Id: I8e0cf7ffa32e86e36e777964eb0c3cc7de02d3c3
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 5ff9c0c..881e8de 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -46,6 +46,7 @@
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
@@ -199,6 +200,12 @@
     @GuardedBy("mLock")
     private SettingsRegistry mSettingsRegistry;
 
+    @GuardedBy("mLock")
+    private HandlerThread mHandlerThread;
+
+    @GuardedBy("mLock")
+    private Handler mBackgroundHandler;
+
     // We have to call in the user manager with no lock held,
     private volatile UserManager mUserManager;
 
@@ -244,6 +251,10 @@
         synchronized (mLock) {
             mUserManager = UserManager.get(getContext());
             mPackageManager = AppGlobals.getPackageManager();
+            mHandlerThread = new HandlerThread(LOG_TAG,
+                    Process.THREAD_PRIORITY_BACKGROUND);
+            mHandlerThread.start();
+            mBackgroundHandler = new Handler(mHandlerThread.getLooper());
             mSettingsRegistry = new SettingsRegistry();
         }
         registerBroadcastReceivers();
@@ -1669,7 +1680,7 @@
             if (mSettingsStates.get(key) == null) {
                 final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
                 SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key,
-                        maxBytesPerPackage);
+                        maxBytesPerPackage, mBackgroundHandler);
                 mSettingsStates.put(key, settingsState);
             }
         }