Merge "Changed Night display strings to "Night Light""
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 81b2524..10c0bc2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -727,6 +727,14 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="com.android.settings.SHORTCUT" />
             </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ZEN_MODE_AUTOMATION_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ACTION_CONDITION_PROVIDER_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.notification.ZenModeSettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
@@ -759,25 +767,6 @@
                 android:value="true" />
         </activity>
 
-        <activity android:name="Settings$ZenModeAutomationSettingsActivity"
-                android:label="@string/zen_mode_automation_settings_title"
-                android:icon="@drawable/ic_settings_notifications"
-                android:exported="true"
-                android:taskAffinity="">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.ZEN_MODE_AUTOMATION_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.ACTION_CONDITION_PROVIDER_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.notification.ZenModeAutomationSettings" />
-            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
-                android:value="true" />
-        </activity>
-
         <activity android:name="Settings$ZenModeAutomationSuggestionActivity"
                 android:label="@string/zen_mode_automation_settings_title"
                 android:icon="@drawable/ic_settings_notifications"
diff --git a/res/layout/instant_app_buttons.xml b/res/layout/instant_app_buttons.xml
new file mode 100644
index 0000000..b267361
--- /dev/null
+++ b/res/layout/instant_app_buttons.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/instant_app_button_container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="4dp"
+    android:paddingStart="8dp"
+    android:paddingEnd="8dp"
+    android:visibility="gone">
+    <Button
+        android:id="@+id/install"
+        style="@style/AppActionPrimaryButton"
+        android:enabled="false"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/install_text"/>
+    <Button
+        android:id="@+id/clear_data"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/clear_instant_app_data"/>
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f5ac227..9f77998 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6418,7 +6418,7 @@
     <!-- Do not disturb: Title for the Priority interruptions option and associated settings page. [CHAR LIMIT=30] -->
     <string name="zen_mode_priority_settings_title">Priority only allows</string>
 
-    <!--  Do not disturb: Title for the zen mode automation option and associated settings page. [CHAR LIMIT=30] -->
+    <!--  Do not disturb: Title for the zen mode automation listing. [CHAR LIMIT=30] -->
     <string name="zen_mode_automation_settings_title">Automatic rules</string>
 
     <!--  Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=30] -->
@@ -7893,9 +7893,6 @@
     <!-- Name of the setting to disable the automatic update -->
     <string name="ota_disable_automatic_update">Automatic system updates</string>
 
-    <!-- Name of the setting to enable hal binderization -->
-    <string name="enable_hal_binderization">Binderized HALs (requires reboot)</string>
-
     <!-- Label for category for data usage [CHAR LIMIT=30] -->
     <string name="usage">Usage</string>
 
@@ -8593,6 +8590,9 @@
     <string name="storage_percent_full">full</string>
 
 
+    <!-- Label for button allow user to clear the data for an instant app -->
+    <string name="clear_instant_app_data">Clear app</string>
+
     <!-- Title of games app storage screen [CHAR LIMIT=30] -->
     <string name="game_storage_settings">Games</string>
 
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 6ed8dc9..e870539 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -90,10 +90,6 @@
         android:summary="@string/color_temperature_desc" />
 
     <SwitchPreference
-        android:key="enable_hal_binderization"
-        android:title="@string/enable_hal_binderization" />
-
-    <SwitchPreference
         android:key="ota_disable_automatic_update"
         android:title="@string/ota_disable_automatic_update" />
 
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details_ia.xml
index 3e06e39..50d183d 100644
--- a/res/xml/installed_app_details_ia.xml
+++ b/res/xml/installed_app_details_ia.xml
@@ -24,10 +24,16 @@
         android:order="-10000"/>
 
     <com.android.settings.applications.LayoutPreference
+        android:key="instant_app_buttons"
+        android:layout="@layout/instant_app_buttons"
+        android:selectable="false"
+        android:order="-9999"/>
+
+    <com.android.settings.applications.LayoutPreference
       android:key="action_buttons"
       android:layout="@layout/app_action_buttons"
       android:selectable="false"
-      android:order="-9999"/>
+      android:order="-9998"/>
 
     <Preference
         android:key="notification_settings"
diff --git a/res/xml/storage_profile_fragment.xml b/res/xml/storage_profile_fragment.xml
index c675744..98cb1dc 100644
--- a/res/xml/storage_profile_fragment.xml
+++ b/res/xml/storage_profile_fragment.xml
@@ -20,22 +20,27 @@
     android:title="@string/storage_settings">
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_photos_videos"
-        android:title="@string/storage_photos_videos">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_photos_videos"
+        android:icon="@drawable/ic_photo_library_vd_theme_24"
+        android:order="2" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_music_audio"
-        android:title="@string/storage_music_audio">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_music_audio"
+        android:icon="@drawable/ic_music_note_vd_theme_24"
+        android:order="3" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_games"
-        android:title="@string/storage_games">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_games"
+        android:icon="@drawable/ic_videogame_vd_theme_24"
+        android:order="4" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_other_apps"
-        android:title="@string/storage_other_apps">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_other_apps"
+        android:icon="@drawable/ic_apps_vd_theme_24"
+        android:order="5" />
     <com.android.settings.deviceinfo.StorageItemPreference
         android:key="pref_files"
-        android:title="@string/storage_files">
-    </com.android.settings.deviceinfo.StorageItemPreference>
+        android:title="@string/storage_files"
+        android:icon="@drawable/ic_folder_vd_theme_24"
+        android:order="6" />
 </PreferenceScreen>
diff --git a/res/xml/zen_mode_automation_settings.xml b/res/xml/zen_mode_automation_settings.xml
deleted file mode 100644
index 7cfffd4..0000000
--- a/res/xml/zen_mode_automation_settings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    android:key="zen_mode_settings"
-    android:title="@string/zen_mode_automation_settings_title" >
-
-    <!-- Rules added at runtime -->
-</PreferenceScreen>
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index b22ad6a..5fc72aa 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -25,15 +25,14 @@
             android:title="@string/zen_mode_priority_settings_title"
             android:fragment="com.android.settings.notification.ZenModePrioritySettings" />
 
-    <!-- Automated rules -->
-    <Preference
-            android:key="automation_settings"
-            android:title="@string/zen_mode_automation_settings_title"
-            android:fragment="com.android.settings.notification.ZenModeAutomationSettings" />
-
     <!-- Visual interruptions -->
     <Preference
             android:key="visual_interruptions_settings"
             android:title="@string/zen_mode_visual_interruptions_settings_title"
             android:fragment="com.android.settings.notification.ZenModeVisualInterruptionSettings" />
+
+    <!-- Automatic rules -->
+    <PreferenceCategory
+        android:key="automatic_rules"
+        android:title="@string/zen_mode_automation_settings_title" />
 </PreferenceScreen>
diff --git a/src/com/android/settings/applications/AppStoreUtil.java b/src/com/android/settings/applications/AppStoreUtil.java
new file mode 100644
index 0000000..f9b95b0
--- /dev/null
+++ b/src/com/android/settings/applications/AppStoreUtil.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+
+// This class provides methods that help dealing with app stores.
+public class AppStoreUtil {
+    private static final String LOG_TAG = "AppStoreUtil";
+
+    private static Intent resolveIntent(Context context, Intent i) {
+        ResolveInfo result = context.getPackageManager().resolveActivity(i, 0);
+        return result != null ? new Intent(i.getAction())
+                .setClassName(result.activityInfo.packageName, result.activityInfo.name) : null;
+    }
+
+    // Returns the package name of the app which installed a given packageName, if one is
+    // available.
+    public static String getInstallerPackageName(Context context, String packageName) {
+        String installerPackageName = null;
+        try {
+            installerPackageName =
+                    context.getPackageManager().getInstallerPackageName(packageName);
+        } catch (IllegalArgumentException e) {
+            Log.e(LOG_TAG, "Exception while retrieving the package installer of " + packageName, e);
+        }
+        if (installerPackageName == null) {
+            return null;
+        }
+        return installerPackageName;
+    }
+
+    // Returns a link to the installer app store for a given package name.
+    public static Intent getAppStoreLink(Context context, String installerPackageName,
+            String packageName) {
+        Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO)
+                .setPackage(installerPackageName);
+        final Intent result = resolveIntent(context, intent);
+        if (result != null) {
+            result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+            return result;
+        }
+        return null;
+    }
+
+    // Convenience method that looks up the installerPackageName for you.
+    public static Intent getAppStoreLink(Context context, String packageName) {
+      String installerPackageName = getInstallerPackageName(context, packageName);
+      return getAppStoreLink(context, installerPackageName, packageName);
+    }
+}
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 1855308..1816793 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications;
 
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
+
 import android.app.Fragment;
 import android.content.Intent;
 import android.view.View;
@@ -30,6 +32,14 @@
     AppHeaderController newAppHeaderController(Fragment fragment, View appHeader);
 
     /**
+     *
+     *  Returns a new {@link InstantAppButtonsController} instance for showing buttons
+     *  only relevant to instant apps.
+     */
+    InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
+            View view);
+
+    /**
      * Calculates the total number of apps installed on the device via policy across all users
      * and managed profiles.
      *
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index ca19dca..7cc899b 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -29,6 +29,7 @@
 import android.util.ArraySet;
 import android.view.View;
 
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 
 import java.util.List;
@@ -57,6 +58,12 @@
     }
 
     @Override
+    public InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
+            View view) {
+        return new InstantAppButtonsController(mContext, fragment, view);
+    }
+
+    @Override
     public void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback) {
         final AllUserPolicyInstalledAppCounter counter =
                 new AllUserPolicyInstalledAppCounter(mContext, mPm, callback);
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index dac10e7..828eca6 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -146,6 +146,7 @@
     private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
 
     private static final String KEY_HEADER = "header_view";
+    private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons";
     private static final String KEY_ACTION_BUTTONS = "action_buttons";
     private static final String KEY_NOTIFICATION = "notification_settings";
     private static final String KEY_STORAGE = "storage_settings";
@@ -222,13 +223,7 @@
         if (isBundled) {
             enabled = handleDisableable(mUninstallButton);
         } else {
-            if ((mPackageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0
-                    && mUserManager.getUsers().size() >= 2) {
-                // When we have multiple users, there is a separate menu
-                // to uninstall for all users.
-                enabled = false;
-            }
-            mUninstallButton.setText(R.string.uninstall_text);
+            enabled = initUnintsallButtonForUserApp();
         }
         // If this is a device admin, it can't be uninstalled or disabled.
         // We do this here so the text of the button is still set correctly.
@@ -298,6 +293,22 @@
         }
     }
 
+    @VisibleForTesting
+    boolean initUnintsallButtonForUserApp() {
+        boolean enabled = true;
+        if ((mPackageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0
+                && mUserManager.getUsers().size() >= 2) {
+            // When we have multiple users, there is a separate menu
+            // to uninstall for all users.
+            enabled = false;
+        } else if (AppUtils.isInstant(mPackageInfo.applicationInfo)) {
+            enabled = false;
+            mUninstallButton.setVisibility(View.GONE);
+        }
+        mUninstallButton.setText(R.string.uninstall_text);
+        return enabled;
+    }
+
     /** Returns if the supplied package is device owner or profile owner of at least one user */
     private boolean isProfileOrDeviceOwner(String packageName) {
         List<UserInfo> userInfos = mUserManager.getUsers();
@@ -455,12 +466,6 @@
         mForceStopButton.setEnabled(false);
     }
 
-    private Intent resolveIntent(Intent i) {
-        ResolveInfo result = getContext().getPackageManager().resolveActivity(i, 0);
-        return result != null ? new Intent(i.getAction())
-                .setClassName(result.activityInfo.packageName, result.activityInfo.name) : null;
-    }
-
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.add(0, UNINSTALL_UPDATES, 0, R.string.app_factory_reset)
@@ -570,6 +575,8 @@
         } else if (PackageUtil.countPackageInUsers(mPm, mUserManager, mPackageName) < 2
                 && (appEntry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
             showIt = false;
+        } else if (AppUtils.isInstant(appEntry.info)) {
+            showIt = false;
         }
         return showIt;
     }
@@ -800,11 +807,15 @@
         }
     }
 
-    private void checkForceStop() {
+    @VisibleForTesting
+    void checkForceStop() {
         if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
             // User can't force stop device admin.
             Log.w(LOG_TAG, "User can't force stop device admin");
             updateForceStopButton(false);
+        } else if (AppUtils.isInstant(mPackageInfo.applicationInfo)) {
+            updateForceStopButton(false);
+            mForceStopButton.setVisibility(View.GONE);
         } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
             // If the app isn't explicitly stopped, then always show the
             // force stop button.
@@ -1064,6 +1075,7 @@
         }
 
         addAppInstallerInfoPref(screen);
+        maybeAddInstantAppButtons();
     }
 
     private boolean isPotentialAppSource() {
@@ -1074,16 +1086,9 @@
     }
 
     private void addAppInstallerInfoPref(PreferenceScreen screen) {
-        String installerPackageName = null;
-        try {
-            installerPackageName =
-                    getContext().getPackageManager().getInstallerPackageName(mPackageName);
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "Exception while retrieving the package installer of " + mPackageName, e);
-        }
-        if (installerPackageName == null) {
-            return;
-        }
+        String installerPackageName =
+                AppStoreUtil.getInstallerPackageName(getContext(), mPackageName);
+
         final CharSequence installerLabel = Utils.getApplicationLabel(getContext(),
                 installerPackageName);
         if (installerLabel == null) {
@@ -1096,18 +1101,31 @@
         pref.setTitle(R.string.app_install_details_title);
         pref.setKey("app_info_store");
         pref.setSummary(getString(R.string.app_install_details_summary, installerLabel));
-        final Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO)
-                .setPackage(installerPackageName);
-        final Intent result = resolveIntent(intent);
-        if (result != null) {
-            result.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
-            pref.setIntent(result);
+
+        Intent intent =
+                AppStoreUtil.getAppStoreLink(getContext(), installerPackageName, mPackageName);
+        if (intent != null) {
+            pref.setIntent(intent);
         } else {
             pref.setEnabled(false);
         }
         category.addPreference(pref);
     }
 
+    @VisibleForTesting
+    void maybeAddInstantAppButtons() {
+        if (AppUtils.isInstant(mPackageInfo.applicationInfo)) {
+            LayoutPreference buttons = (LayoutPreference) findPreference(KEY_INSTANT_APP_BUTTONS);
+            final Activity activity = getActivity();
+            FeatureFactory.getFactory(activity)
+                    .getApplicationFeatureProvider(activity)
+                    .newInstantAppButtonsController(this,
+                            buttons.findViewById(R.id.instant_app_button_container))
+                    .setPackageName(mPackageName)
+                    .show();
+        }
+    }
+
     private boolean hasPermission(String permission) {
         if (mPackageInfo == null || mPackageInfo.requestedPermissions == null) {
             return false;
diff --git a/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
new file mode 100644
index 0000000..aa7c418
--- /dev/null
+++ b/src/com/android/settings/applications/instantapps/InstantAppButtonsController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.instantapps;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.applications.AppStoreUtil;
+import com.android.settings.overlay.FeatureFactory;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+/** Encapsulates a container for buttons relevant to instant apps */
+public class InstantAppButtonsController {
+
+    private final Context mContext;
+    private final Fragment mFragment;
+    private final View mView;
+    private String mPackageName;
+
+    public InstantAppButtonsController(Context context, Fragment fragment, View view) {
+      mContext = context;
+      mFragment = fragment;
+      mView = view;
+    }
+
+    public InstantAppButtonsController setPackageName(String packageName) {
+        mPackageName = packageName;
+        return this;
+    }
+
+    public void bindButtons() {
+        Button installButton = (Button)mView.findViewById(R.id.install);
+        Button clearDataButton = (Button)mView.findViewById(R.id.clear_data);
+        Intent installIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName);
+        if (installIntent != null) {
+            installButton.setEnabled(true);
+            installButton.setOnClickListener(v -> mFragment.startActivity(installIntent));
+        }
+        clearDataButton.setOnClickListener(v -> {
+            FeatureFactory.getFactory(mContext).getMetricsFeatureProvider().action(mContext,
+                    MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP, mPackageName);
+            PackageManager pm = mContext.getPackageManager();
+            pm.clearApplicationUserData(mPackageName, null);
+        });
+    }
+
+    public InstantAppButtonsController show() {
+        bindButtons();
+        mView.setVisibility(View.VISIBLE);
+        return this;
+    }
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 03b3d39..d1bb9d6 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -103,7 +103,6 @@
 import com.android.settings.notification.NotificationStation;
 import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.ZenAccessSettings;
-import com.android.settings.notification.ZenModeAutomationSettings;
 import com.android.settings.notification.ZenModeEventRuleSettings;
 import com.android.settings.notification.ZenModePrioritySettings;
 import com.android.settings.notification.ZenModeScheduleRuleSettings;
@@ -207,7 +206,6 @@
             ApnEditor.class.getName(),
             WifiCallingSettings.class.getName(),
             ZenModePrioritySettings.class.getName(),
-            ZenModeAutomationSettings.class.getName(),
             ZenModeScheduleRuleSettings.class.getName(),
             ZenModeEventRuleSettings.class.getName(),
             ZenModeVisualInterruptionSettings.class.getName(),
diff --git a/src/com/android/settings/development/DevelopmentSettings.java b/src/com/android/settings/development/DevelopmentSettings.java
index da6e800..041019b 100644
--- a/src/com/android/settings/development/DevelopmentSettings.java
+++ b/src/com/android/settings/development/DevelopmentSettings.java
@@ -230,8 +230,6 @@
     private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
 
     private static final String OTA_DISABLE_AUTOMATIC_UPDATE_KEY = "ota_disable_automatic_update";
-    private static final String ENABLE_HAL_BINDERIZATION_KEY = "enable_hal_binderization";
-    private static final String ENABLE_HAL_BINDERIZATION_PROPERTY = "persist.hal.binderization";
 
     private static final int RESULT_DEBUG_APP = 1000;
     private static final int RESULT_MOCK_LOCATION_APP = 1001;
@@ -291,7 +289,6 @@
     private ListPreference mBluetoothSelectA2dpLdacPlaybackQuality;
 
     private SwitchPreference mOtaDisableAutomaticUpdate;
-    private SwitchPreference mEnableHalBinderization;
     private SwitchPreference mWifiAllowScansWithTraffic;
     private SwitchPreference mStrictMode;
     private SwitchPreference mPointerLocation;
@@ -550,8 +547,6 @@
 
         mOtaDisableAutomaticUpdate = findAndInitSwitchPref(OTA_DISABLE_AUTOMATIC_UPDATE_KEY);
 
-        mEnableHalBinderization = findAndInitSwitchPref(ENABLE_HAL_BINDERIZATION_KEY);
-
         mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
         mColorModePreference.updateCurrentAndSupported();
         if (mColorModePreference.getColorModeCount() < 2) {
@@ -795,7 +790,6 @@
         updateShowAllANRsOptions();
         updateVerifyAppsOverUsbOptions();
         updateOtaDisableAutomaticUpdateOptions();
-        updateEnableHalBinderizationOptions();
         updateBugreportOptions();
         updateForceRtlOptions();
         updateLogdSizeValues();
@@ -1040,17 +1034,6 @@
                 mOtaDisableAutomaticUpdate.isChecked() ? 0 : 1);
     }
 
-    private void updateEnableHalBinderizationOptions() {
-        updateSwitchPreference(mEnableHalBinderization,
-                SystemProperties.getBoolean(ENABLE_HAL_BINDERIZATION_PROPERTY, false));
-    }
-
-    private void writeEnableHalBinderizationOptions() {
-        SystemProperties.set(ENABLE_HAL_BINDERIZATION_PROPERTY,
-                             mEnableHalBinderization.isChecked() ? "true" : "false");
-        pokeSystemProperties();
-    }
-
     private boolean enableVerifierSetting() {
         final ContentResolver cr = getActivity().getContentResolver();
         if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
@@ -2481,8 +2464,6 @@
             writeVerifyAppsOverUsbOptions();
         } else if (preference == mOtaDisableAutomaticUpdate) {
             writeOtaDisableAutomaticUpdateOptions();
-        } else if (preference == mEnableHalBinderization) {
-            writeEnableHalBinderizationOptions();
         } else if (preference == mStrictMode) {
             writeStrictModeVisualOptions();
         } else if (preference == mPointerLocation) {
diff --git a/src/com/android/settings/deviceinfo/StorageProfileFragment.java b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
index 1a24962..c5d1045 100644
--- a/src/com/android/settings/deviceinfo/StorageProfileFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
@@ -73,8 +73,7 @@
 
         mPreferenceController.setVolume(mVolume);
         mUserId = args.getInt(USER_ID_EXTRA, UserHandle.myUserId());
-        // TODO(b/36224168): Use the user id to appropriately badge the preferences.
-        mPreferenceController.setUserId(mUserId);
+        mPreferenceController.setUserId(UserHandle.of(mUserId));
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index e22aa24..5b27592 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -20,6 +20,9 @@
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
@@ -165,8 +168,35 @@
     /**
      * Sets the user id for which this preference controller is handling.
      */
-    public void setUserId(int userId) {
-        mUserId = userId;
+    public void setUserId(UserHandle userHandle) {
+        mUserId = userHandle.getIdentifier();
+
+        PackageManager pm = mContext.getPackageManager();
+        badgePreference(pm, userHandle, mPhotoPreference);
+        badgePreference(pm, userHandle, mAudioPreference);
+        badgePreference(pm, userHandle, mGamePreference);
+        badgePreference(pm, userHandle, mAppPreference);
+        badgePreference(pm, userHandle, mSystemPreference);
+        badgePreference(pm, userHandle, mFilePreference);
+    }
+
+    private void badgePreference(PackageManager pm, UserHandle userHandle, Preference preference) {
+        if (preference != null) {
+            Drawable currentIcon = preference.getIcon();
+            // Sigh... Applying the badge to the icon clobbers the tint on the base drawable.
+            // For some reason, re-applying it here means the tint remains.
+            currentIcon = applyTint(mContext, currentIcon);
+            preference.setIcon(pm.getUserBadgedIcon(currentIcon, userHandle));
+        }
+    }
+
+    private static Drawable applyTint(Context context, Drawable icon) {
+        TypedArray array =
+                context.obtainStyledAttributes(new int[]{android.R.attr.colorControlNormal});
+        icon = icon.mutate();
+        icon.setTint(array.getColor(0, 0));
+        array.recycle();
+        return icon;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
deleted file mode 100644
index 495e499..0000000
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import android.app.AlertDialog;
-import android.app.AutomaticZenRule;
-import android.app.NotificationManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.service.notification.ConditionProviderService;
-import android.service.notification.ZenModeConfig;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.view.View;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.utils.ManagedServiceSettings.Config;
-import com.android.settings.utils.ZenServiceListing;
-
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Map;
-
-public class ZenModeAutomationSettings extends ZenModeSettingsBase {
-
-    static final Config CONFIG = getConditionProviderConfig();
-
-    private PackageManager mPm;
-    private ZenServiceListing mServiceListing;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.zen_mode_automation_settings);
-        mPm = mContext.getPackageManager();
-        mServiceListing = new ZenServiceListing(mContext, CONFIG);
-        mServiceListing.reloadApprovedServices();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-    }
-
-    @Override
-    protected void onZenModeChanged() {
-        // don't care
-    }
-
-    @Override
-    protected void onZenModeConfigChanged() {
-        updateControls();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (isUiRestricted()) {
-            return;
-        }
-        updateControls();
-    }
-
-    private void showAddRuleDialog() {
-        new ZenRuleSelectionDialog(mContext, mServiceListing) {
-            @Override
-            public void onSystemRuleSelected(ZenRuleInfo ri) {
-                showNameRuleDialog(ri);
-            }
-
-            @Override
-            public void onExternalRuleSelected(ZenRuleInfo ri) {
-                Intent intent = new Intent().setComponent(ri.configurationActivity);
-                startActivity(intent);
-            }
-        }.show();
-    }
-
-    private void showNameRuleDialog(final ZenRuleInfo ri) {
-        new ZenRuleNameDialog(mContext, null) {
-            @Override
-            public void onOk(String ruleName) {
-                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE_OK);
-                AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
-                        ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
-                        true);
-                String savedRuleId = addZenRule(rule);
-                if (savedRuleId != null) {
-                    startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
-                }
-            }
-        }.show();
-    }
-
-    private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName) {
-        new AlertDialog.Builder(mContext)
-                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
-                .setNegativeButton(R.string.cancel, null)
-                .setPositiveButton(R.string.zen_mode_delete_rule_button,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mMetricsFeatureProvider.action(mContext,
-                                MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
-                        removeZenRule(ruleId);
-                    }
-                })
-                .show();
-    }
-
-    private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
-            String ruleId) {
-        Intent intent = new Intent()
-                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
-                .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
-        if (configurationActivity != null) {
-            intent.setComponent(configurationActivity);
-        } else {
-            intent.setAction(settingsAction);
-        }
-        return intent;
-    }
-
-    private Map.Entry<String,AutomaticZenRule>[] sortedRules() {
-        final Map.Entry<String,AutomaticZenRule>[] rt =
-                mRules.toArray(new Map.Entry[mRules.size()]);
-        Arrays.sort(rt, RULE_COMPARATOR);
-        return rt;
-    }
-
-    private void updateControls() {
-        final PreferenceScreen root = getPreferenceScreen();
-        root.removeAll();
-        final Map.Entry<String,AutomaticZenRule>[] sortedRules = sortedRules();
-        for (Map.Entry<String,AutomaticZenRule> sortedRule : sortedRules) {
-            ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
-            if (pref.appExists) {
-                root.addPreference(pref);
-            }
-        }
-        final Preference p = new Preference(getPrefContext());
-        p.setIcon(R.drawable.ic_add);
-        p.setTitle(R.string.zen_mode_add_rule);
-        p.setPersistent(false);
-        p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE);
-                showAddRuleDialog();
-                return true;
-            }
-        });
-        root.addPreference(p);
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.NOTIFICATION_ZEN_MODE_AUTOMATION;
-    }
-
-    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
-            CharSequence providerLabel) {
-        final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
-        final String ruleState = (rule == null || !rule.isEnabled())
-                ? getString(R.string.switch_off_text)
-                : getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
-
-        return isSystemRule ? ruleState
-                : getString(R.string.zen_mode_rule_summary_provider_combination,
-                        providerLabel, ruleState);
-    }
-
-    private static Config getConditionProviderConfig() {
-        final Config c = new Config();
-        c.tag = TAG;
-        c.setting = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
-        c.secondarySetting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
-        c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
-        c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
-        c.noun = "condition provider";
-        return c;
-    }
-
-    private static String computeZenModeCaption(Resources res, int zenMode) {
-        switch (zenMode) {
-            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
-                return res.getString(R.string.zen_mode_option_alarms);
-            case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
-                return res.getString(R.string.zen_mode_option_important_interruptions);
-            case NotificationManager.INTERRUPTION_FILTER_NONE:
-                return res.getString(R.string.zen_mode_option_no_interruptions);
-            default:
-                return null;
-        }
-    }
-
-    public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
-        if (si == null || si.metaData == null) return null;
-        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
-        final ComponentName configurationActivity = getSettingsActivity(si);
-        if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
-            final ZenRuleInfo ri = new ZenRuleInfo();
-            ri.serviceComponent = new ComponentName(si.packageName, si.name);
-            ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
-            ri.title = ruleType;
-            ri.packageName = si.packageName;
-            ri.configurationActivity = getSettingsActivity(si);
-            ri.packageLabel = si.applicationInfo.loadLabel(pm);
-            ri.ruleInstanceLimit =
-                    si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
-            return ri;
-        }
-        return null;
-    }
-
-    private static ComponentName getSettingsActivity(ServiceInfo si) {
-        if (si == null || si.metaData == null) return null;
-        final String configurationActivity =
-                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
-        if (configurationActivity != null) {
-            return ComponentName.unflattenFromString(configurationActivity);
-        }
-        return null;
-    }
-
-    private static final Comparator<Map.Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
-            new Comparator<Map.Entry<String,AutomaticZenRule>>() {
-        @Override
-        public int compare(Map.Entry<String,AutomaticZenRule> lhs,
-                Map.Entry<String,AutomaticZenRule> rhs) {
-            int byDate = Long.compare(lhs.getValue().getCreationTime(),
-                    rhs.getValue().getCreationTime());
-            if (byDate != 0) {
-                return byDate;
-            } else {
-                return key(lhs.getValue()).compareTo(key(rhs.getValue()));
-            }
-        }
-
-        private String key(AutomaticZenRule rule) {
-            final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId()) ? 1
-                    : ZenModeConfig.isValidEventConditionId(rule.getConditionId()) ? 2
-                    : 3;
-            return type + rule.getName().toString();
-        }
-    };
-
-    private class ZenRulePreference extends Preference {
-        final CharSequence mName;
-        final String mId;
-        final boolean appExists;
-
-        public ZenRulePreference(Context context,
-                final Map.Entry<String, AutomaticZenRule> ruleEntry) {
-            super(context);
-
-            final AutomaticZenRule rule = ruleEntry.getValue();
-            mName = rule.getName();
-            mId = ruleEntry.getKey();
-
-            final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
-                    rule.getConditionId());
-            final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
-            final boolean isSystemRule = isSchedule || isEvent;
-
-            try {
-                ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
-                LoadIconTask task = new LoadIconTask(this);
-                task.execute(info);
-                setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
-            } catch (PackageManager.NameNotFoundException e) {
-                setIcon(R.drawable.ic_label);
-                appExists = false;
-                return;
-            }
-
-            appExists = true;
-            setTitle(rule.getName());
-            setPersistent(false);
-
-            final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
-                    : isEvent ? ZenModeEventRuleSettings.ACTION : "";
-            ServiceInfo si = mServiceListing.findService(rule.getOwner());
-            ComponentName settingsActivity = getSettingsActivity(si);
-            setIntent(getRuleIntent(action, settingsActivity, mId));
-            setSelectable(settingsActivity != null || isSystemRule);
-
-            setWidgetLayoutResource(R.layout.zen_rule_widget);
-        }
-
-        @Override
-        public void onBindViewHolder(PreferenceViewHolder view) {
-            super.onBindViewHolder(view);
-
-            View v = view.findViewById(R.id.delete_zen_rule);
-            if (v != null) {
-                v.setOnClickListener(mDeleteListener);
-            }
-            view.setDividerAllowedAbove(true);
-            view.setDividerAllowedBelow(true);
-        }
-
-        private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showDeleteRuleDialog(mId, mName);
-            }
-        };
-    }
-
-    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
-        private final WeakReference<Preference> prefReference;
-
-        public LoadIconTask(Preference pref) {
-            prefReference = new WeakReference<>(pref);
-        }
-
-        @Override
-        protected Drawable doInBackground(ApplicationInfo... params) {
-            return params[0].loadIcon(mPm);
-        }
-
-        @Override
-        protected void onPostExecute(Drawable icon) {
-            if (icon != null) {
-                final Preference pref = prefReference.get();
-                if (pref != null) {
-                    pref.setIcon(icon);
-                }
-            }
-        }
-    }
-
-}
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 695049f..bbcaa9c 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -16,29 +16,56 @@
 
 package com.android.settings.notification;
 
+import android.app.AlertDialog;
 import android.app.AutomaticZenRule;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.provider.Settings;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.ZenModeConfig;
+import com.android.settings.utils.ManagedServiceSettings;
+import com.android.settings.utils.ZenServiceListing;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.View;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Set;
 
 public class ZenModeSettings extends ZenModeSettingsBase {
     private static final String KEY_PRIORITY_SETTINGS = "priority_settings";
     private static final String KEY_VISUAL_SETTINGS = "visual_interruptions_settings";
+    private static final String KEY_AUTOMATIC_RULES = "automatic_rules";
 
+    static final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
+
+    private PreferenceCategory mAutomaticRules;
     private Preference mPrioritySettings;
     private Preference mVisualSettings;
     private Policy mPolicy;
     private SummaryBuilder mSummaryBuilder;
+    private PackageManager mPm;
+    private ZenServiceListing mServiceListing;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -47,10 +74,14 @@
         addPreferencesFromResource(R.xml.zen_mode_settings);
         final PreferenceScreen root = getPreferenceScreen();
 
+        mAutomaticRules = (PreferenceCategory) root.findPreference(KEY_AUTOMATIC_RULES);
         mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS);
         mVisualSettings = root.findPreference(KEY_VISUAL_SETTINGS);
         mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
         mSummaryBuilder = new SummaryBuilder(getContext());
+        mPm = mContext.getPackageManager();
+        mServiceListing = new ZenServiceListing(mContext, CONFIG);
+        mServiceListing.reloadApprovedServices();
     }
 
     @Override
@@ -59,6 +90,7 @@
         if (isUiRestricted()) {
             return;
         }
+        updateControls();
     }
 
     @Override
@@ -80,6 +112,7 @@
     private void updateControls() {
         updatePrioritySettingsSummary();
         updateVisualSettingsSummary();
+        updateAutomaticRules();
     }
 
     private void updatePrioritySettingsSummary() {
@@ -90,11 +123,251 @@
         mVisualSettings.setSummary(mSummaryBuilder.getVisualSettingSummary(mPolicy));
     }
 
+    private void updateAutomaticRules() {
+        mAutomaticRules.removeAll();
+        final Map.Entry<String,AutomaticZenRule>[] sortedRules = sortedRules();
+        for (Map.Entry<String,AutomaticZenRule> sortedRule : sortedRules) {
+            ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
+            if (pref.appExists) {
+                mAutomaticRules.addPreference(pref);
+            }
+        }
+        final Preference p = new Preference(getPrefContext());
+        p.setIcon(R.drawable.ic_add);
+        p.setTitle(R.string.zen_mode_add_rule);
+        p.setPersistent(false);
+        p.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE);
+                showAddRuleDialog();
+                return true;
+            }
+        });
+        mAutomaticRules.addPreference(p);
+    }
+
+    private void showAddRuleDialog() {
+        new ZenRuleSelectionDialog(mContext, mServiceListing) {
+            @Override
+            public void onSystemRuleSelected(ZenRuleInfo ri) {
+                showNameRuleDialog(ri);
+            }
+
+            @Override
+            public void onExternalRuleSelected(ZenRuleInfo ri) {
+                Intent intent = new Intent().setComponent(ri.configurationActivity);
+                startActivity(intent);
+            }
+        }.show();
+    }
+
+    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
+            CharSequence providerLabel) {
+        final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
+        final String ruleState = (rule == null || !rule.isEnabled())
+                ? getString(R.string.switch_off_text)
+                : getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
+
+        return isSystemRule ? ruleState
+                : getString(R.string.zen_mode_rule_summary_provider_combination,
+                        providerLabel, ruleState);
+    }
+
+    private static ManagedServiceSettings.Config getConditionProviderConfig() {
+        final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config();
+        c.tag = TAG;
+        c.setting = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
+        c.secondarySetting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
+        c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
+        c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
+        c.noun = "condition provider";
+        return c;
+    }
+
+    private static String computeZenModeCaption(Resources res, int zenMode) {
+        switch (zenMode) {
+            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
+                return res.getString(R.string.zen_mode_option_alarms);
+            case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
+                return res.getString(R.string.zen_mode_option_important_interruptions);
+            case NotificationManager.INTERRUPTION_FILTER_NONE:
+                return res.getString(R.string.zen_mode_option_no_interruptions);
+            default:
+                return null;
+        }
+    }
+
+    public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
+        if (si == null || si.metaData == null) return null;
+        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
+        final ComponentName configurationActivity = getSettingsActivity(si);
+        if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
+            final ZenRuleInfo ri = new ZenRuleInfo();
+            ri.serviceComponent = new ComponentName(si.packageName, si.name);
+            ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
+            ri.title = ruleType;
+            ri.packageName = si.packageName;
+            ri.configurationActivity = getSettingsActivity(si);
+            ri.packageLabel = si.applicationInfo.loadLabel(pm);
+            ri.ruleInstanceLimit =
+                    si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+            return ri;
+        }
+        return null;
+    }
+
+    private static ComponentName getSettingsActivity(ServiceInfo si) {
+        if (si == null || si.metaData == null) return null;
+        final String configurationActivity =
+                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
+        if (configurationActivity != null) {
+            return ComponentName.unflattenFromString(configurationActivity);
+        }
+        return null;
+    }
+
+    private void showNameRuleDialog(final ZenRuleInfo ri) {
+        new ZenRuleNameDialog(mContext, null) {
+            @Override
+            public void onOk(String ruleName) {
+                mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE_OK);
+                AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
+                        ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
+                        true);
+                String savedRuleId = addZenRule(rule);
+                if (savedRuleId != null) {
+                    startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
+                }
+            }
+        }.show();
+    }
+
+    private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName) {
+        new AlertDialog.Builder(mContext)
+                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
+                .setNegativeButton(R.string.cancel, null)
+                .setPositiveButton(R.string.zen_mode_delete_rule_button,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                mMetricsFeatureProvider.action(mContext,
+                                        MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
+                                removeZenRule(ruleId);
+                            }
+                        })
+                .show();
+    }
+
+    private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
+            String ruleId) {
+        Intent intent = new Intent()
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
+        if (configurationActivity != null) {
+            intent.setComponent(configurationActivity);
+        } else {
+            intent.setAction(settingsAction);
+        }
+        return intent;
+    }
+
+    private Map.Entry<String,AutomaticZenRule>[] sortedRules() {
+        final Map.Entry<String,AutomaticZenRule>[] rt =
+                mRules.toArray(new Map.Entry[mRules.size()]);
+        Arrays.sort(rt, RULE_COMPARATOR);
+        return rt;
+    }
+
     @Override
     protected int getHelpResource() {
         return R.string.help_uri_interruptions;
     }
 
+    private class ZenRulePreference extends Preference {
+        final CharSequence mName;
+        final String mId;
+        final boolean appExists;
+
+        public ZenRulePreference(Context context,
+                final Map.Entry<String, AutomaticZenRule> ruleEntry) {
+            super(context);
+
+            final AutomaticZenRule rule = ruleEntry.getValue();
+            mName = rule.getName();
+            mId = ruleEntry.getKey();
+
+            final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
+                    rule.getConditionId());
+            final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
+            final boolean isSystemRule = isSchedule || isEvent;
+
+            try {
+                ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
+                LoadIconTask task = new LoadIconTask(this);
+                task.execute(info);
+                setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
+            } catch (PackageManager.NameNotFoundException e) {
+                setIcon(R.drawable.ic_label);
+                appExists = false;
+                return;
+            }
+
+            appExists = true;
+            setTitle(rule.getName());
+            setPersistent(false);
+
+            final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
+                    : isEvent ? ZenModeEventRuleSettings.ACTION : "";
+            ServiceInfo si = mServiceListing.findService(rule.getOwner());
+            ComponentName settingsActivity = getSettingsActivity(si);
+            setIntent(getRuleIntent(action, settingsActivity, mId));
+            setSelectable(settingsActivity != null || isSystemRule);
+
+            setWidgetLayoutResource(R.layout.zen_rule_widget);
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder view) {
+            super.onBindViewHolder(view);
+
+            View v = view.findViewById(R.id.delete_zen_rule);
+            if (v != null) {
+                v.setOnClickListener(mDeleteListener);
+            }
+        }
+
+        private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showDeleteRuleDialog(mId, mName);
+            }
+        };
+    }
+
+    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
+        private final WeakReference<Preference> prefReference;
+
+        public LoadIconTask(Preference pref) {
+            prefReference = new WeakReference<>(pref);
+        }
+
+        @Override
+        protected Drawable doInBackground(ApplicationInfo... params) {
+            return params[0].loadIcon(mPm);
+        }
+
+        @Override
+        protected void onPostExecute(Drawable icon) {
+            if (icon != null) {
+                final Preference pref = prefReference.get();
+                if (pref != null) {
+                    pref.setIcon(icon);
+                }
+            }
+        }
+    }
+
     public static class SummaryBuilder {
 
         private Context mContext;
@@ -180,6 +453,29 @@
         private boolean isEffectSuppressed(Policy policy, int effect) {
             return (policy.suppressedVisualEffects & effect) != 0;
         }
-
     }
+
+    private static final Comparator<Map.Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
+            new Comparator<Map.Entry<String,AutomaticZenRule>>() {
+                @Override
+                public int compare(Map.Entry<String,AutomaticZenRule> lhs,
+                        Map.Entry<String,AutomaticZenRule> rhs) {
+                    int byDate = Long.compare(lhs.getValue().getCreationTime(),
+                            rhs.getValue().getCreationTime());
+                    if (byDate != 0) {
+                        return byDate;
+                    } else {
+                        return key(lhs.getValue()).compareTo(key(rhs.getValue()));
+                    }
+                }
+
+                private String key(AutomaticZenRule rule) {
+                    final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
+                            ? 1
+                            : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
+                                    ? 2
+                                    : 3;
+                    return type + rule.getName().toString();
+                }
+            };
 }
diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
index 9de9a60..4fa632a 100644
--- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java
+++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
@@ -169,7 +169,7 @@
             if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
             Set<ZenRuleInfo> externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
             for (ServiceInfo serviceInfo : services) {
-                final ZenRuleInfo ri = ZenModeAutomationSettings.getRuleInfo(mPm, serviceInfo);
+                final ZenRuleInfo ri = ZenModeSettings.getRuleInfo(mPm, serviceInfo);
                 if (ri != null && ri.configurationActivity != null
                         && mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
                         && (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 1ed25f2..d0e21e926 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -149,7 +149,6 @@
     @Override
     public void onResume() {
         mWifiInfo = mWifiManager.getConnectionInfo();
-        mWifiConfig = mWifiManager.getWifiApConfiguration();
 
         refreshFromWifiInfo();
         setIpText();
@@ -257,4 +256,17 @@
         }
         mDnsPref.setDetailText(builder.toString());
     }
+
+    /**
+     * Forgets the wifi network associated with this preference.
+     */
+    public void forgetNetwork() {
+        if (mWifiConfig.ephemeral) {
+            mWifiManager.disableEphemeralNetwork(mWifiConfig.SSID);
+        } else if (mWifiConfig.isPasspoint()) {
+            mWifiManager.removePasspointConfiguration(mWifiConfig.FQDN);
+        } else {
+            mWifiManager.forget(mWifiConfig.networkId, null /* action listener */);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 0073202..ade9d6a 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -19,6 +19,7 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.view.View;
 import android.widget.Button;
 
 import com.android.internal.logging.nano.MetricsProto;
@@ -69,17 +70,9 @@
     }
 
     private void forgetNetwork() {
-        WifiInfo info = mWifiDetailPreferenceController.getWifiInfo();
         mMetricsFeatureProvider.action(getActivity(), MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
-        if (!info.isEphemeral()) {
-                // Network is active but has no network ID - must be ephemeral.
-                mWifiManager.disableEphemeralNetwork(
-                        AccessPoint.convertToQuotedString(info.getSSID()));
-        } else if (mAccessPoint.getConfig().isPasspoint()) {
-            mWifiManager.removePasspointConfiguration(mAccessPoint.getConfig().FQDN);
-        } else {
-            mWifiManager.forget(info.getNetworkId(), null /* action listener */);
-        }
+        mWifiDetailPreferenceController.forgetNetwork();
+        mForgetButton.setEnabled(false);
     }
 
     @Override
diff --git a/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java b/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
new file mode 100644
index 0000000..e7e5e19
--- /dev/null
+++ b/tests/app/src/com/android/settings/notification/ZenModeSettingsIntegrationTest.java
@@ -0,0 +1,53 @@
+package com.android.settings.notification;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ZenModeSettingsIntegrationTest {
+    private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
+
+    private Context mContext;
+    private UiDevice mUiDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mUiDevice.wakeUp();
+        mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
+    }
+
+    @Test
+    public void testAutomaticRulesAppear() {
+        launchZenSettings();
+        onView(withText("Automatic rules")).check(matches(isDisplayed()));
+        onView(withText("Weekend")).check(matches(isDisplayed()));
+        onView(withText("Add more")).check(matches(isDisplayed())).perform(click());
+        onView(withText("Choose rule type")).check(matches(isDisplayed()));
+    }
+
+    private void launchZenSettings() {
+        Intent settingsIntent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
+                .setPackage(mContext.getPackageName())
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(settingsIntent);
+    }
+}
diff --git a/tests/robotests/src/android/net/NetworkScorerAppData.java b/tests/robotests/src/android/net/NetworkScorerAppData.java
index 1eaa8a7..f7da4d1 100644
--- a/tests/robotests/src/android/net/NetworkScorerAppData.java
+++ b/tests/robotests/src/android/net/NetworkScorerAppData.java
@@ -23,13 +23,20 @@
      * wifi networks automatically" feature.
      */
     private final ComponentName mEnableUseOpenWifiActivity;
+    /**
+     * The {@link android.app.NotificationChannel} ID used by {@link #mRecommendationService} to
+     * post open network notifications.
+     */
+    private final String mNetworkAvailableNotificationChannelId;
 
     public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
-            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity) {
+            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity,
+            String networkAvailableNotificationChannelId) {
         this.packageUid = packageUid;
         this.mRecommendationService = recommendationServiceComp;
         this.mRecommendationServiceLabel = recommendationServiceLabel;
         this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+        this.mNetworkAvailableNotificationChannelId = networkAvailableNotificationChannelId;
     }
 
     protected NetworkScorerAppData(Parcel in) {
@@ -37,6 +44,7 @@
         mRecommendationService = ComponentName.readFromParcel(in);
         mRecommendationServiceLabel = in.readString();
         mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+        mNetworkAvailableNotificationChannelId = in.readString();
     }
 
     @Override
@@ -45,6 +53,7 @@
         ComponentName.writeToParcel(mRecommendationService, dest);
         dest.writeString(mRecommendationServiceLabel);
         ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+        dest.writeString(mNetworkAvailableNotificationChannelId);
     }
 
     @Override
@@ -83,6 +92,11 @@
         return mRecommendationServiceLabel;
     }
 
+    @Nullable
+    public String getNetworkAvailableNotificationChannelId() {
+        return mNetworkAvailableNotificationChannelId;
+    }
+
     @Override
     public String toString() {
         return "NetworkScorerAppData{" +
@@ -90,6 +104,8 @@
                 ", mRecommendationService=" + mRecommendationService +
                 ", mRecommendationServiceLabel=" + mRecommendationServiceLabel +
                 ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+                ", mNetworkAvailableNotificationChannelId=" +
+                mNetworkAvailableNotificationChannelId +
                 '}';
     }
 
@@ -101,12 +117,14 @@
         return packageUid == that.packageUid &&
                 Objects.equals(mRecommendationService, that.mRecommendationService) &&
                 Objects.equals(mRecommendationServiceLabel, that.mRecommendationServiceLabel) &&
-                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity) &&
+                Objects.equals(mNetworkAvailableNotificationChannelId,
+                        that.mNetworkAvailableNotificationChannelId);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(packageUid, mRecommendationService, mRecommendationServiceLabel,
-                mEnableUseOpenWifiActivity);
+                mEnableUseOpenWifiActivity, mNetworkAvailableNotificationChannelId);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index bf00889..209cdeb 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -23,11 +23,18 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.view.View;
+import android.widget.Button;
 
 import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.applications.instantapps.InstantAppButtonsController;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
 
 import org.junit.Before;
@@ -41,6 +48,7 @@
 import org.robolectric.util.ReflectionHelpers;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -51,6 +59,11 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public final class InstalledAppDetailsTest {
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+
+    @Mock
+    ApplicationFeatureProvider mApplicationFeatureProvider;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private UserManager mUserManager;
@@ -65,6 +78,10 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mAppDetail = new InstalledAppDetails();
+
+        // Default to not considering any apps to be instant (individual tests can override this).
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                (InstantAppDataProvider) (i -> false));
     }
 
     @Test
@@ -136,4 +153,119 @@
         assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isTrue();
         verify(mActivity, never()).finishAndRemoveTask();
     }
+
+    // Tests that we don't show the "uninstall for all users" button for instant apps.
+    @Test
+    public void instantApps_noUninstallForAllButton() {
+        // Make this app appear to be instant.
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                (InstantAppDataProvider) (i -> true));
+        when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
+        when(mUserManager.getUsers().size()).thenReturn(2);
+
+        final ApplicationInfo info = new ApplicationInfo();
+        info.enabled = true;
+        final AppEntry appEntry = mock(AppEntry.class);
+        appEntry.info = info;
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+
+        ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
+        ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
+
+        assertThat(mAppDetail.shouldShowUninstallForAll(appEntry)).isFalse();
+    }
+
+    // Tests that we don't show the uninstall button for instant apps"
+    @Test
+    public void instantApps_noUninstallButton() {
+        // Make this app appear to be instant.
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                                         (InstantAppDataProvider) (i -> true));
+        final ApplicationInfo info = new ApplicationInfo();
+        info.flags = ApplicationInfo.FLAG_INSTALLED;
+        info.enabled = true;
+        final AppEntry appEntry = mock(AppEntry.class);
+        appEntry.info = info;
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        packageInfo.applicationInfo = info;
+        final Button uninstallButton = mock(Button.class);
+
+        ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
+        ReflectionHelpers.setField(mAppDetail, "mAppEntry", appEntry);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
+        ReflectionHelpers.setField(mAppDetail, "mUninstallButton", uninstallButton);
+
+        mAppDetail.initUnintsallButtonForUserApp();
+        verify(uninstallButton).setVisibility(View.GONE);
+    }
+
+    // Tests that we don't show the force stop button for instant apps (they aren't allowed to run
+    // when they aren't in the foreground).
+    @Test
+    public void instantApps_noForceStop() {
+        // Make this app appear to be instant.
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                (InstantAppDataProvider) (i -> true));
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        final AppEntry appEntry = mock(AppEntry.class);
+        final ApplicationInfo info = new ApplicationInfo();
+        appEntry.info = info;
+        final Button forceStopButton = mock(Button.class);
+
+        ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
+        ReflectionHelpers.setField(mAppDetail, "mAppEntry", appEntry);
+        ReflectionHelpers.setField(mAppDetail, "mForceStopButton", forceStopButton);
+
+        mAppDetail.checkForceStop();
+        verify(forceStopButton).setVisibility(View.GONE);
+    }
+
+    // A helper class for testing the InstantAppButtonsController - it lets us look up the
+    // preference associated with a key for instant app buttons and get back a mock
+    // LayoutPreference (to avoid a null pointer exception).
+    public static class InstalledAppDetailsWithMockInstantButtons extends InstalledAppDetails {
+        @Mock
+        private LayoutPreference mInstantButtons;
+
+        public InstalledAppDetailsWithMockInstantButtons() {
+            super();
+            MockitoAnnotations.initMocks(this);
+        }
+
+        @Override
+        public Preference findPreference(CharSequence key) {
+            if (key == "instant_app_buttons") {
+                return mInstantButtons;
+            }
+            return super.findPreference(key);
+        }
+    }
+
+    @Test
+    public void instantApps_instantSpecificButtons() {
+        // Make this app appear to be instant.
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                (InstantAppDataProvider) (i -> true));
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+
+        final InstalledAppDetailsWithMockInstantButtons
+                fragment = new InstalledAppDetailsWithMockInstantButtons();
+        ReflectionHelpers.setField(fragment, "mPackageInfo", packageInfo);
+
+        final InstantAppButtonsController buttonsController =
+                mock(InstantAppButtonsController.class);
+        when(buttonsController.setPackageName(anyString())).thenReturn(buttonsController);
+
+        FakeFeatureFactory.setupForTest(mContext);
+        FakeFeatureFactory factory =
+                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        when(factory.applicationFeatureProvider.newInstantAppButtonsController(any(),
+                any())).thenReturn(buttonsController);
+
+        fragment.maybeAddInstantAppButtons();
+        verify(buttonsController).setPackageName(anyString());
+        verify(buttonsController).show();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 18b0c82..7d1f79b 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -31,6 +31,7 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
 import android.support.v7.preference.PreferenceScreen;
@@ -243,4 +244,43 @@
         assertThat(system.getSummary().toString()).isEqualTo("16.00KB");
         assertThat(files.getSummary().toString()).isEqualTo("5.00KB");
     }
+
+    @Test
+    public void settingUserIdAppliesNewIcons() {
+        StorageItemPreference audio = spy(new StorageItemPreference(mContext));
+        audio.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference image = spy(new StorageItemPreference(mContext));
+        image.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference games = spy(new StorageItemPreference(mContext));
+        games.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference apps = spy(new StorageItemPreference(mContext));
+        apps.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference system = spy(new StorageItemPreference(mContext));
+        system.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        StorageItemPreference files = spy(new StorageItemPreference(mContext));
+        files.setIcon(R.drawable.ic_photo_library_vd_theme_24);
+        PreferenceScreen screen = mock(PreferenceScreen.class);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.AUDIO_KEY))).thenReturn(audio);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.PHOTO_KEY))).thenReturn(image);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.OTHER_APPS_KEY))).thenReturn(apps);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.SYSTEM_KEY))).thenReturn(system);
+        when(screen.findPreference(
+                eq(StorageItemPreferenceController.FILES_KEY))).thenReturn(files);
+        mController.displayPreference(screen);
+
+        mController.setUserId(new UserHandle(10));
+
+        verify(audio, times(2)).setIcon(any(Drawable.class));
+        verify(image, times(2)).setIcon(any(Drawable.class));
+        verify(games, times(2)).setIcon(any(Drawable.class));
+        verify(apps, times(2)).setIcon(any(Drawable.class));
+        verify(system, times(2)).setIcon(any(Drawable.class));
+        verify(files, times(2)).setIcon(any(Drawable.class));
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
index 6bf47ac..1e468a3 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
@@ -68,7 +68,8 @@
         Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
         ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
         NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */);
+                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
+                null /* networkAvailableNotificationChannelId */);
         when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
         Preference preference = mock(Preference.class);
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
index fef6f85..bb8635f 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerTest.java
@@ -118,7 +118,8 @@
     public void testUpdateCandidates_validScorer() {
         ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
         NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */);
+                0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
+                null /* networkAvailableNotificationChannelId */);
         when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
                 Lists.newArrayList(scorerAppData));
         when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
diff --git a/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
index aa89464..5b55006 100644
--- a/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/UseOpenWifiPreferenceControllerTest.java
@@ -56,9 +56,9 @@
 public class UseOpenWifiPreferenceControllerTest {
     private static ComponentName ENABLE_ACTIVITY_COMPONENT = new ComponentName("package", "activityClass");
     private static NetworkScorerAppData APP_DATA =
-            new NetworkScorerAppData(0, null, null, ENABLE_ACTIVITY_COMPONENT);
+            new NetworkScorerAppData(0, null, null, ENABLE_ACTIVITY_COMPONENT, null);
     private static NetworkScorerAppData APP_DATA_NO_ACTIVITY =
-            new NetworkScorerAppData(0, null, null, null);
+            new NetworkScorerAppData(0, null, null, null, null);
 
     @Mock private Lifecycle mLifecycle;
     @Mock private Fragment mFragment;
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index a7e12b3..88a63b3 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -84,8 +84,6 @@
         MockitoAnnotations.initMocks(this);
 
         mLifecycle = new Lifecycle();
-        mController = new WifiDetailPreferenceController(
-                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
 
         when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
         when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
@@ -93,11 +91,13 @@
         when(mockAccessPoint.getRssi()).thenReturn(RSSI);
         when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
 
+        mController = new WifiDetailPreferenceController(
+                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
+
         setupMockedPreferenceScreen();
 
-        when (mockWifiInfo.getRssi()).thenReturn(RSSI);
+        when(mockWifiInfo.getRssi()).thenReturn(RSSI);
         when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo);
-        when(mockWifiManager.getWifiApConfiguration()).thenReturn(mockWifiConfig);
     }
 
     private void setupMockedPreferenceScreen() {
@@ -139,7 +139,6 @@
         mController.onResume();
 
         verify(mockWifiManager).getConnectionInfo();
-        verify(mockWifiManager).getWifiApConfiguration();
     }
 
     @Test
@@ -178,4 +177,29 @@
 
         verify(mockSignalStrengthPref).setDetailText(expectedStrength);
     }
+
+    @Test
+    public void forgetNetwork_ephemeral() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.SSID = "ssid";
+        // WifiConfiguration#isEphemeral will not be visible in robolectric until O is supported
+        wifiConfiguration.ephemeral = true;
+        when(mockAccessPoint.getConfig()).thenReturn(wifiConfiguration);
+
+        mController = new WifiDetailPreferenceController(
+                mockAccessPoint, mContext, mLifecycle, mockWifiManager);
+
+        mController.forgetNetwork();
+
+        verify(mockWifiManager).disableEphemeralNetwork(wifiConfiguration.SSID);
+    }
+
+    @Test
+    public void forgetNetwork_saved() {
+        mockWifiConfig.networkId = 5;
+
+        mController.forgetNetwork();
+
+        verify(mockWifiManager).forget(mockWifiConfig.networkId, null);
+    }
 }