Merge "Use the right userId when setting guest restrictions"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ecc465e..8928307 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6864,6 +6864,12 @@
     <!-- Zen mode access settings - summary for warning dialog when enabling access [CHAR LIMIT=NONE] -->
     <string name="zen_access_warning_dialog_summary">The app will be able to turn on/off Do Not Disturb and make changes to related settings.</string>
 
+    <!-- Zen mode access settings - title for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+    <string name="zen_access_revoke_warning_dialog_title">Revoke access to Do Not Disturb for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
+
+    <!-- Zen mode access settings - summary for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+    <string name="zen_access_revoke_warning_dialog_summary">All Do Not Disturb rules created by this app will be removed.</string>
+
     <!-- Ignore battery optimizations on label [CHAR LIMIT=30] -->
     <string name="ignore_optimizations_on">Don\u2019t optimize</string>
 
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index c25d2d3..9bccbcf 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -66,7 +66,7 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.HardwareRenderer;
+import android.view.ThreadedRenderer;
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -1023,7 +1023,7 @@
     }
 
     private void updateTrackFrameTimeOptions() {
-        String value = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
+        String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
         if (value == null) {
             value = "";
         }
@@ -1041,7 +1041,7 @@
     }
 
     private void writeTrackFrameTimeOptions(Object newValue) {
-        SystemProperties.set(HardwareRenderer.PROFILE_PROPERTY,
+        SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY,
                 newValue == null ? "" : newValue.toString());
         pokeSystemProperties();
         updateTrackFrameTimeOptions();
@@ -1049,7 +1049,7 @@
 
     private void updateShowNonRectClipOptions() {
         String value = SystemProperties.get(
-                HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
+                ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
         if (value == null) {
             value = "hide";
         }
@@ -1067,7 +1067,7 @@
     }
 
     private void writeShowNonRectClipOptions(Object newValue) {
-        SystemProperties.set(HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
+        SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
                 newValue == null ? "" : newValue.toString());
         pokeSystemProperties();
         updateShowNonRectClipOptions();
@@ -1075,28 +1075,28 @@
 
     private void updateShowHwScreenUpdatesOptions() {
         updateSwitchPreference(mShowHwScreenUpdates,
-                SystemProperties.getBoolean(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
+                SystemProperties.getBoolean(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
     }
 
     private void writeShowHwScreenUpdatesOptions() {
-        SystemProperties.set(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
+        SystemProperties.set(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
                 mShowHwScreenUpdates.isChecked() ? "true" : null);
         pokeSystemProperties();
     }
 
     private void updateShowHwLayersUpdatesOptions() {
         updateSwitchPreference(mShowHwLayersUpdates, SystemProperties.getBoolean(
-                HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
+                ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
     }
 
     private void writeShowHwLayersUpdatesOptions() {
-        SystemProperties.set(HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
+        SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
                 mShowHwLayersUpdates.isChecked() ? "true" : null);
         pokeSystemProperties();
     }
 
     private void updateDebugHwOverdrawOptions() {
-        String value = SystemProperties.get(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY);
+        String value = SystemProperties.get(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY);
         if (value == null) {
             value = "";
         }
@@ -1114,7 +1114,7 @@
     }
 
     private void writeDebugHwOverdrawOptions(Object newValue) {
-        SystemProperties.set(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY,
+        SystemProperties.set(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY,
                 newValue == null ? "" : newValue.toString());
         pokeSystemProperties();
         updateDebugHwOverdrawOptions();
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 809a740..ce07299 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -32,6 +32,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.nfc.NfcAdapter;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -453,6 +454,7 @@
     @Override
     protected void onCreate(Bundle savedState) {
         super.onCreate(savedState);
+        long startTime = System.currentTimeMillis();
 
         // Should happen before any call to getIntent()
         getMetaData();
@@ -506,7 +508,15 @@
         if (mIsShowingDashboard) {
             // Run the Index update only if we have some space
             if (!Utils.isLowStorage(this)) {
-                Index.getInstance(getApplicationContext()).update();
+                long indexStartTime = System.currentTimeMillis();
+                AsyncTask.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        Index.getInstance(getApplicationContext()).update();
+                    }
+                });
+                if (DEBUG_TIMING) Log.d(LOG_TAG, "Index.update() took "
+                        + (System.currentTimeMillis() - indexStartTime) + " ms");
             } else {
                 Log.w(LOG_TAG, "Cannot update the Indexer as we are running low on storage space!");
             }
@@ -621,6 +631,8 @@
         }
 
         mHomeActivitiesCount = getHomeActivitiesCount();
+        if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+                + " ms");
     }
 
     private int getHomeActivitiesCount() {
@@ -955,6 +967,18 @@
     }
 
     private void updateTilesList() {
+        // Generally the items that are will be changing from these updates will
+        // not be in the top list of tiles, so run it in the background and the
+        // SettingsDrawerActivity will pick up on the updates automatically.
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                doUpdateTilesList();
+            }
+        });
+    }
+
+    private void doUpdateTilesList() {
         PackageManager pm = getPackageManager();
         final UserManager um = UserManager.get(this);
         final boolean isAdmin = um.isAdminUser();
@@ -1009,7 +1033,7 @@
 
         if (UserHandle.MU_ENABLED && !isAdmin) {
             // When on restricted users, disable all extra categories (but only the settings ones).
-            List<DashboardCategory> categories = getDashboardCategories(true);
+            List<DashboardCategory> categories = getDashboardCategories();
             for (DashboardCategory category : categories) {
                 for (DashboardTile tile : category.tiles) {
                     ComponentName component = tile.intent.getComponent();
@@ -1020,8 +1044,6 @@
                 }
             }
         }
-
-        updateDrawer();
     }
 
     private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin,
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 55a2c32..27ab6a2 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -68,7 +68,6 @@
     private static final String KEY_PROXY_SETTINGS = "proxy_settings";
     private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
     private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan";
-    private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
     private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
 
     public static final String EXIT_ECM_RESULT = "exit_ecm_result";
@@ -327,26 +326,6 @@
             p.setEnabled(!TetherSettings
                     .isProvisioningNeededButUnavailable(getActivity()));
         }
-
-        // Enable link to CMAS app settings depending on the value in config.xml.
-        boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
-                com.android.internal.R.bool.config_cellBroadcastAppLinks);
-        try {
-            if (isCellBroadcastAppLinkEnabled) {
-                if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
-                        == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
-                    isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
-                }
-            }
-        } catch (IllegalArgumentException ignored) {
-            isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
-        }
-        if (!isAdmin || !isCellBroadcastAppLinkEnabled
-                || mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
-            PreferenceScreen root = getPreferenceScreen();
-            Preference ps = findPreference(KEY_CELL_BROADCAST_SETTINGS);
-            if (ps != null) root.removePreference(ps);
-        }
     }
 
     @Override
@@ -478,23 +457,6 @@
                     result.add(KEY_TETHER_SETTINGS);
                 }
 
-                // Enable link to CMAS app settings depending on the value in config.xml.
-                boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
-                        com.android.internal.R.bool.config_cellBroadcastAppLinks);
-                try {
-                    if (isCellBroadcastAppLinkEnabled) {
-                        if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
-                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
-                            isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
-                        }
-                    }
-                } catch (IllegalArgumentException ignored) {
-                    isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
-                }
-                if (isSecondaryUser || !isCellBroadcastAppLinkEnabled) {
-                    result.add(KEY_CELL_BROADCAST_SETTINGS);
-                }
-
                 return result;
             }
         };
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 54a5ff4..64eb356 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,13 +16,7 @@
 
 package com.android.settings.dashboard;
 
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
@@ -38,11 +32,14 @@
 import com.android.settings.Settings;
 import com.android.settings.SettingsActivity;
 import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
 
 import java.util.List;
 
-public class DashboardSummary extends InstrumentedFragment {
-    public static final boolean DEBUG = true;
+public class DashboardSummary extends InstrumentedFragment
+        implements SettingsDrawerActivity.CategoryListener {
+    public static final boolean DEBUG = false;
+    private static final boolean DEBUG_TIMING = false;
     private static final String TAG = "DashboardSummary";
 
     public static final String[] INITIAL_ITEMS = new String[] {
@@ -56,8 +53,6 @@
 
     private static final int MSG_REBUILD_UI = 1;
 
-    private final HomePackageReceiver mHomePackageReceiver = new HomePackageReceiver();
-
     private RecyclerView mDashboard;
     private DashboardAdapter mAdapter;
     private SummaryLoader mSummaryLoader;
@@ -71,11 +66,19 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        long startTime = System.currentTimeMillis();
         List<DashboardCategory> categories =
-                ((SettingsActivity) getActivity()).getDashboardCategories(true);
-        mAdapter = new DashboardAdapter(getContext(), categories);
-        mSummaryLoader = new SummaryLoader(getActivity(), mAdapter, categories);
+                ((SettingsActivity) getActivity()).getDashboardCategories();
+        mSummaryLoader = new SummaryLoader(getActivity(), categories);
         setHasOptionsMenu(true);
+        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+                + " ms");
+    }
+
+    @Override
+    public void onDestroy() {
+        mSummaryLoader.release();
+        super.onDestroy();
     }
 
     @Override
@@ -90,14 +93,7 @@
     public void onResume() {
         super.onResume();
 
-        sendRebuildUI();
-
-        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
-        filter.addDataScheme("package");
-        getActivity().registerReceiver(mHomePackageReceiver, filter);
+        ((SettingsDrawerActivity) getActivity()).addCategoryListener(this);
         mSummaryLoader.setListening(true);
     }
 
@@ -105,7 +101,7 @@
     public void onPause() {
         super.onPause();
 
-        getActivity().unregisterReceiver(mHomePackageReceiver);
+        ((SettingsDrawerActivity) getActivity()).remCategoryListener(this);
         mSummaryLoader.setListening(false);
     }
 
@@ -123,10 +119,10 @@
         mDashboard.setLayoutManager(llm);
         mDashboard.setHasFixedSize(true);
 
-        rebuildUI(getContext());
+        rebuildUI();
     }
 
-    private void rebuildUI(Context context) {
+    private void rebuildUI() {
         if (!isAdded()) {
             Log.w(TAG, "Cannot build the DashboardSummary UI yet as the Fragment is not added");
             return;
@@ -135,7 +131,7 @@
         long start = System.currentTimeMillis();
         // TODO: Cache summaries from old categories somehow.
         List<DashboardCategory> categories =
-                ((SettingsActivity) getActivity()).getDashboardCategories(true);
+                ((SettingsActivity) getActivity()).getDashboardCategories();
         boolean showingAll = mAdapter != null && mAdapter.isShowingAll();
         mAdapter = new DashboardAdapter(getContext(), categories);
         mSummaryLoader.setAdapter(mAdapter);
@@ -146,29 +142,8 @@
         Log.d(TAG, "rebuildUI took: " + delta + " ms");
     }
 
-    private void sendRebuildUI() {
-        if (!mHandler.hasMessages(MSG_REBUILD_UI)) {
-            mHandler.sendEmptyMessage(MSG_REBUILD_UI);
-        }
+    @Override
+    public void onCategoriesChanged() {
+        rebuildUI();
     }
-
-    private Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_REBUILD_UI: {
-                    final Context context = getActivity();
-                    rebuildUI(context);
-                } break;
-            }
-        }
-    };
-
-    private class HomePackageReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            rebuildUI(context);
-        }
-    }
-
 }
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index a5481ac..a9dd43a 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -16,9 +16,11 @@
 package com.android.settings.dashboard;
 
 import android.app.Activity;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
 import android.util.ArrayMap;
 import android.util.Log;
 import com.android.settings.SettingsActivity;
@@ -39,38 +41,48 @@
     private final ArrayMap<SummaryProvider, DashboardTile> mSummaryMap = new ArrayMap<>();
     private final List<DashboardTile> mTiles = new ArrayList<>();
 
+    private final Worker mWorker;
+    private final Handler mHandler;
+    private final HandlerThread mWorkerThread;
+
     private DashboardAdapter mAdapter;
 
-    public SummaryLoader(Activity activity, DashboardAdapter adapter,
-                  List<DashboardCategory> categories) {
+    public SummaryLoader(Activity activity, List<DashboardCategory> categories) {
+        mHandler = new Handler();
+        mWorkerThread = new HandlerThread("SummaryLoader");
+        mWorkerThread.start();
+        mWorker = new Worker(mWorkerThread.getLooper());
         mActivity = activity;
-        mAdapter = adapter;
         for (int i = 0; i < categories.size(); i++) {
             List<DashboardTile> tiles = categories.get(i).tiles;
             for (int j = 0; j < tiles.size(); j++) {
                 DashboardTile tile = tiles.get(j);
-                SummaryProvider provider = getSummaryProvider(tile);
-                if (provider != null) {
-                    mSummaryMap.put(provider, tile);
-                }
+                mWorker.obtainMessage(Worker.MSG_GET_PROVIDER, tile).sendToTarget();
             }
         }
     }
 
+    public void release() {
+        mWorkerThread.quit();
+    }
+
     public void setAdapter(DashboardAdapter adapter) {
         mAdapter = adapter;
     }
 
-    public void setSummary(SummaryProvider provider, CharSequence summary) {
-        DashboardTile tile = mSummaryMap.get(provider);
-        tile.summary = summary;
-        mAdapter.notifyChanged(tile);
+    public void setSummary(SummaryProvider provider, final CharSequence summary) {
+        final DashboardTile tile = mSummaryMap.get(provider);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                tile.summary = summary;
+                mAdapter.notifyChanged(tile);
+            }
+        });
     }
 
     public void setListening(boolean listening) {
-        for (SummaryProvider provider : mSummaryMap.keySet()) {
-            provider.setListening(listening);
-        }
+        mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
     }
 
     private SummaryProvider getSummaryProvider(DashboardTile tile) {
@@ -107,14 +119,7 @@
     }
 
     private Bundle getMetaData(DashboardTile tile) {
-        // TODO: Cache this in TileUtils so this doesn't need to be loaded again.
-        try {
-            ActivityInfo activityInfo = mActivity.getPackageManager().getActivityInfo(
-                    tile.intent.getComponent(), PackageManager.GET_META_DATA);
-            return activityInfo.metaData;
-        } catch (PackageManager.NameNotFoundException e) {
-            return null;
-        }
+        return tile.metaData;
     }
 
     public interface SummaryProvider {
@@ -124,4 +129,34 @@
     public interface SummaryProviderFactory {
         SummaryProvider createSummaryProvider(Activity activity, SummaryLoader summaryLoader);
     }
+
+    private class Worker extends Handler {
+        private static final int MSG_GET_PROVIDER = 1;
+        private static final int MSG_SET_LISTENING = 2;
+
+        public Worker(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_GET_PROVIDER:
+                    DashboardTile tile = (DashboardTile) msg.obj;
+                    SummaryProvider provider = getSummaryProvider(tile);
+                    if (provider != null) {
+                        if (DEBUG) Log.d(TAG, "Creating " + tile);
+                        mSummaryMap.put(provider, tile);
+                    }
+                    break;
+                case MSG_SET_LISTENING:
+                    boolean listening = msg.arg1 != 0;
+                    if (DEBUG) Log.d(TAG, "Listening " + listening);
+                    for (SummaryProvider p : mSummaryMap.keySet()) {
+                        p.setListening(listening);
+                    }
+                    break;
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/nfc/PaymentSettings.java b/src/com/android/settings/nfc/PaymentSettings.java
index 42545b9..985a1e6 100644
--- a/src/com/android/settings/nfc/PaymentSettings.java
+++ b/src/com/android/settings/nfc/PaymentSettings.java
@@ -115,8 +115,10 @@
                 PaymentBackend paymentBackend = new PaymentBackend(mContext);
                 paymentBackend.refresh();
                 PaymentAppInfo app = paymentBackend.getDefaultApp();
-                mSummaryLoader.setSummary(this, mContext.getString(R.string.payment_summary,
-                        app.label));
+                if (app != null) {
+                    mSummaryLoader.setSummary(this, mContext.getString(R.string.payment_summary,
+                            app.label));
+                }
             }
         }
     }
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 9e27528..11517ea 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -76,6 +76,7 @@
     private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
     private static final String KEY_WIFI_DISPLAY = "wifi_display";
     private static final String KEY_ZEN_MODE = "zen_mode";
+    private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
 
     private static final String[] RESTRICTED_KEYS = {
         KEY_MEDIA_VOLUME,
@@ -105,6 +106,7 @@
     private ComponentName mSuppressor;
     private int mRingerMode = -1;
 
+    private PackageManager mPm;
     private UserManager mUserManager;
     private RingtonePreference mRequestPreference;
 
@@ -117,6 +119,7 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContext = getActivity();
+        mPm = getPackageManager();
         mUserManager = UserManager.get(getContext());
         mVoiceCapable = Utils.isVoiceCapable(mContext);
 
@@ -143,6 +146,24 @@
                             com.android.internal.R.drawable.ic_audio_ring_notif_mute);
             removePreference(KEY_RING_VOLUME);
         }
+
+        // Enable link to CMAS app settings depending on the value in config.xml.
+        boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
+                com.android.internal.R.bool.config_cellBroadcastAppLinks);
+        try {
+            if (isCellBroadcastAppLinkEnabled) {
+                if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+                        == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+                    isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
+                }
+            }
+        } catch (IllegalArgumentException ignored) {
+            isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
+        }
+        if (!mUserManager.isAdminUser() || !isCellBroadcastAppLinkEnabled
+                || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
+            removePreference(KEY_CELL_BROADCAST_SETTINGS);
+        }
         initRingtones();
         initVibrateWhenRinging();
         updateRingerMode();
@@ -545,7 +566,7 @@
         public List<SearchIndexableResource> getXmlResourcesToIndex(
                 Context context, boolean enabled) {
             final SearchIndexableResource sir = new SearchIndexableResource(context);
-            sir.xmlResId = R.xml.configure_notification_settings;
+            sir.xmlResId = R.xml.sound_settings;
             return Arrays.asList(sir);
         }
 
@@ -559,6 +580,27 @@
                 rt.add(KEY_WIFI_DISPLAY);
                 rt.add(KEY_VIBRATE_WHEN_RINGING);
             }
+
+            final PackageManager pm = context.getPackageManager();
+            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+
+            // Enable link to CMAS app settings depending on the value in config.xml.
+            boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
+                    com.android.internal.R.bool.config_cellBroadcastAppLinks);
+            try {
+                if (isCellBroadcastAppLinkEnabled) {
+                    if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+                        isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
+                    }
+                }
+            } catch (IllegalArgumentException ignored) {
+                isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
+            }
+            if (!um.isAdminUser() || !isCellBroadcastAppLinkEnabled) {
+                rt.add(KEY_CELL_BROADCAST_SETTINGS);
+            }
+
             return rt;
         }
     };
diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java
index 1c85f4d..4cec0b4 100644
--- a/src/com/android/settings/notification/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/ZenAccessSettings.java
@@ -119,15 +119,15 @@
                 @Override
                 public boolean onPreferenceChange(Preference preference, Object newValue) {
                     final boolean access = (Boolean) newValue;
-                    if (!access) {
-                        // disabling access
-                        setAccess(mContext, pkg, access);
-                        return true;
+                    if (access) {
+                        new ScaryWarningDialogFragment()
+                                .setPkgInfo(pkg, label)
+                                .show(getFragmentManager(), "dialog");
+                    } else {
+                        new FriendlyWarningDialogFragment()
+                                .setPkgInfo(pkg, label)
+                                .show(getFragmentManager(), "dialog");
                     }
-                    // enabling access: show a scary dialog first
-                    new ScaryWarningDialogFragment()
-                            .setPkgInfo(pkg, label)
-                            .show(getFragmentManager(), "dialog");
                     return false;
                 }
             });
@@ -149,6 +149,16 @@
         });
     }
 
+    private static void deleteRules(final Context context, final String pkg) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+                mgr.removeAutomaticZenRules(pkg);
+            }
+        });
+    }
+
     private final class SettingObserver extends ContentObserver {
         public SettingObserver() {
             super(new Handler(Looper.getMainLooper()));
@@ -160,6 +170,9 @@
         }
     }
 
+    /**
+     * Warning dialog when allowing zen access warning about the privileges being granted.
+     */
     public static class ScaryWarningDialogFragment extends DialogFragment {
         static final String KEY_PKG = "p";
         static final String KEY_LABEL = "l";
@@ -202,4 +215,51 @@
                     .create();
         }
     }
+
+    /**
+     * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
+     */
+    public static class FriendlyWarningDialogFragment extends DialogFragment {
+        static final String KEY_PKG = "p";
+        static final String KEY_LABEL = "l";
+
+        public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+            Bundle args = new Bundle();
+            args.putString(KEY_PKG, pkg);
+            args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+            setArguments(args);
+            return this;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            final Bundle args = getArguments();
+            final String pkg = args.getString(KEY_PKG);
+            final String label = args.getString(KEY_LABEL);
+
+            final String title = getResources().getString(
+                    R.string.zen_access_revoke_warning_dialog_title, label);
+            final String summary = getResources()
+                    .getString(R.string.zen_access_revoke_warning_dialog_summary);
+            return new AlertDialog.Builder(getContext())
+                    .setMessage(summary)
+                    .setTitle(title)
+                    .setCancelable(true)
+                    .setPositiveButton(R.string.okay,
+                            new DialogInterface.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int id) {
+                                    deleteRules(getContext(), pkg);
+                                    setAccess(getContext(), pkg, false);
+                                }
+                            })
+                    .setNegativeButton(R.string.cancel,
+                            new DialogInterface.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int id) {
+                                    // pass
+                                }
+                            })
+                    .create();
+        }
+    }
 }
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 376b2eb..6d6ca08 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -155,7 +155,7 @@
         sResMap.put(SoundSettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(SoundSettings.class.getName()),
-                        R.xml.sound_settings,
+                        NO_DATA_RES_ID,
                         SoundSettings.class.getName(),
                         R.drawable.ic_settings_sound));