Use a broadcast receiver instead of a settings observer.

Settings observer doesn't work if a setting is modified in another
process, hence we instead register a receiver which listens for a signal
from the settings process that the rotation preference has changed.

Change-Id: I570e3c67bb64a32347e84ca00a8ac31d9010eac3
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index dc63a76..6dfe0eb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -403,22 +403,34 @@
     FocusIndicatorView mFocusHandler;
 
     @Thunk boolean mRotationEnabled = false;
-    private boolean mPreferenceObserverRegistered = false;
+    private boolean mScreenOrientationSettingReceiverRegistered = false;
 
-    final private SharedPreferences.OnSharedPreferenceChangeListener mSettingsObserver =
-            new SharedPreferences.OnSharedPreferenceChangeListener() {
-        @Override
-        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
-            if (Utilities.ALLOW_ROTATION_PREFERENCE_KEY.equals(key)) {
-                if (mRotationEnabled = sharedPreferences.getBoolean(
-                        Utilities.ALLOW_ROTATION_PREFERENCE_KEY, false)) {
-                    unlockScreenOrientation(true);
-                } else {
-                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
+    final private BroadcastReceiver mScreenOrientationSettingReceiver =
+            new BroadcastReceiver() {
+                @Thunk Runnable mUpdateOrientationRunnable = new Runnable() {
+                    public void run() {
+                        setOrientation();
+                    }
+                };
+
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    mRotationEnabled = intent.getBooleanExtra(
+                            Utilities.SCREEN_ROTATION_SETTING_EXTRA, false);
+                    if (!waitUntilResume(mUpdateOrientationRunnable, true)) {
+                        setOrientation();
+                    }
                 }
-            }
+            };
+
+    @Thunk void setOrientation() {
+        if (mRotationEnabled) {
+            unlockScreenOrientation(true);
+        } else {
+            setRequestedOrientation(
+                    ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
         }
-    };
+    }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -520,16 +532,18 @@
         // In case we are on a device with locked rotation, we should look at preferences to check
         // if the user has specifically allowed rotation.
         if (!mRotationEnabled) {
-            getSharedPreferences(LauncherFiles.ROTATION_PREF_FILE,
-                    Context.MODE_MULTI_PROCESS).registerOnSharedPreferenceChangeListener(
-                    mSettingsObserver);
-            mPreferenceObserverRegistered = true;
+            String updateOrientationBroadcastPermission = getResources().getString(
+                    R.string.receive_update_orientation_broadcasts_permission);
+            registerReceiver(mScreenOrientationSettingReceiver,
+                    new IntentFilter(Utilities.SCREEN_ROTATION_SETTING_INTENT),
+                    updateOrientationBroadcastPermission, null);
+            mScreenOrientationSettingReceiverRegistered = true;
             mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext());
         }
 
         // On large interfaces, or on devices that a user has specifically enabled screen rotation,
         // we want the screen to auto-rotate based on the current orientation
-        unlockScreenOrientation(true);
+        setOrientation();
 
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onCreate(savedInstanceState);
@@ -2016,11 +2030,9 @@
     public void onDestroy() {
         super.onDestroy();
 
-        if (mPreferenceObserverRegistered) {
-            getSharedPreferences(LauncherFiles.ROTATION_PREF_FILE,
-                    Context.MODE_MULTI_PROCESS).unregisterOnSharedPreferenceChangeListener(
-                    mSettingsObserver);
-            mPreferenceObserverRegistered = false;
+        if (mScreenOrientationSettingReceiverRegistered) {
+            unregisterReceiver(mScreenOrientationSettingReceiver);
+            mScreenOrientationSettingReceiverRegistered = false;
         }
 
         // Remove all pending runnables
@@ -3663,7 +3675,7 @@
      *
      * @return {@code true} if we are currently paused. The caller might be able to skip some work
      */
-    private boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
+    @Thunk boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
         if (mPaused) {
             if (LOGD) Log.d(TAG, "Deferring update until onResume");
             if (deletePreviousRunnables) {
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index a1da1b6..27763f5 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -18,12 +18,14 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
+import android.preference.Preference;
 import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
 
 /**
- * Settings activity for Launcher. Currently implements the following setting:
- * LockToPortrait
+ * Settings activity for Launcher. Currently implements the following setting: Allow rotation
  */
 public class SettingsActivity extends Activity {
     @Override
@@ -41,13 +43,25 @@
      */
     @SuppressWarnings("WeakerAccess")
     public static class LauncherSettingsFragment extends PreferenceFragment {
-
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
-            getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
+            getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
             getPreferenceManager().setSharedPreferencesName(LauncherFiles.ROTATION_PREF_FILE);
             addPreferencesFromResource(R.xml.launcher_preferences);
         }
+
+        @Override
+        public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+                                             Preference preference) {
+            boolean allowRotation = getPreferenceManager().getSharedPreferences().getBoolean(
+                    Utilities.ALLOW_ROTATION_PREFERENCE_KEY, false);
+            Intent rotationSetting = new Intent(Utilities.SCREEN_ROTATION_SETTING_INTENT);
+            String launchBroadcastPermission = getResources().getString(
+                            R.string.receive_update_orientation_broadcasts_permission);
+            rotationSetting.putExtra(Utilities.SCREEN_ROTATION_SETTING_EXTRA, allowRotation);
+            getActivity().sendBroadcast(rotationSetting, launchBroadcastPermission);
+            return true;
+        }
     }
 }
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index cffcd34..b267f75 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -93,6 +93,9 @@
     private static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
 
     public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
+    public static final String SCREEN_ROTATION_SETTING_INTENT =
+            "come.android.launcher3.SCREEN_ORIENTATION_PREF_CHANGED";
+    public static final String SCREEN_ROTATION_SETTING_EXTRA = "screenRotationPref";
 
     public static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);