Merge "Change reset page to be SUW style"
diff --git a/Android.mk b/Android.mk
index 6b0d077..f10b3ec 100644
--- a/Android.mk
+++ b/Android.mk
@@ -41,6 +41,7 @@
     androidx.lifecycle_lifecycle-extensions \
     guava \
     jsr305 \
+    contextualcards \
     settings-logtags \
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
@@ -57,7 +58,14 @@
 
 include $(BUILD_PACKAGE)
 
+# ====  prebuilt library  ========================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
+    contextualcards:libs/contextualcards.aar
+include $(BUILD_MULTI_PREBUILT)
+
 # Use the following include to make our test apk.
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
+endif
\ No newline at end of file
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index aa53bdb..94be61c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3192,6 +3192,15 @@
             android:exported="true"
             android:permission="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA" />
 
+        <provider
+            android:name=".homepage.contextualcards.SettingsContextualCardProvider"
+            android:authorities="com.android.settings.homepage.contextualcards"
+            android:permission="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.content.action.SETTINGS_HOMEPAGE_DATA"/>
+            </intent-filter>
+        </provider>
         <!-- This is the longest AndroidManifest.xml ever. -->
     </application>
 </manifest>
diff --git a/libs/contextualcards.aar b/libs/contextualcards.aar
new file mode 100755
index 0000000..a44a26c
--- /dev/null
+++ b/libs/contextualcards.aar
Binary files differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 119e1fb..d78b7b0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -384,15 +384,15 @@
     <!-- Summary for bluetooth item in connection detail page. (phone)-->
     <string name="bluetooth_pref_summary" product="default">Allow your phone to communicate with nearby Bluetooth devices</string>
 
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=40] -->
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload">Disable Bluetooth A2DP hardware offload</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=20] -->
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload_dialog_title">Restart Device?</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=60] -->
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload_dialog_message">You need to restart your device to change this setting.</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=10] -->
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload_dialog_confirm">Restart</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=10] -->
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload_dialog_cancel">Cancel</string>
 
     <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
@@ -414,6 +414,9 @@
     <!-- Toast text for hint user bluetooth is turned on [CHAR LIMIT=none]-->
     <string name="connected_device_bluetooth_turned_on_toast">Bluetooth turned on</string>
 
+    <!-- Title to see all the previous connected devices [CHAR LIMIT=50] -->
+    <string name="previous_connected_see_all">See all</string>
+
     <!-- Date & time settings screen title -->
     <string name="date_and_time">Date &amp; time</string>
     <!-- The title of the activity to pick a time zone. -->
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 684d032..81afc1a 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -68,6 +68,12 @@
         settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceController" />
 
     <Preference
+        android:key="data_settings_v2"
+        android:title="@string/data_usage_app_summary_title"
+        android:summary="@string/summary_placeholder"
+        settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceControllerV2" />
+
+    <Preference
         android:key="time_spent_in_app"
         android:title="@string/time_spent_in_app_pref_title"
         settings:controller="com.android.settings.applications.appinfo.TimeSpentInAppPreferenceController" />
diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index 424ca75..29c9e01 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -41,18 +41,24 @@
         settings:useAdminDisabledSummary="true"
         settings:controller="com.android.settings.connecteddevice.AddDevicePreferenceController"/>
 
-    <Preference
+    <PreferenceCategory
         android:key="previously_connected_devices"
         android:title="@string/connected_device_previously_connected_title"
-        android:icon="@drawable/ic_devices_other_black"
-        android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"
-        settings:allowDividerAbove="true"
-        settings:controller="com.android.settings.connecteddevice.PreviouslyConnectedDevicePreferenceController"/>
+        settings:controller="com.android.settings.connecteddevice.PreviouslyConnectedDevicePreferenceController">
+
+        <Preference
+            android:key="previously_connected_devices_see_all"
+            android:title="@string/previous_connected_see_all"
+            android:icon="@drawable/ic_chevron_right_24dp"
+            android:order="10"
+            android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"/>
+    </PreferenceCategory>
 
     <Preference
         android:key="connection_preferences"
         android:title="@string/connected_device_connections_title"
         android:fragment="com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment"
+        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.connecteddevice.AdvancedConnectedDeviceController"/>
 
 </PreferenceScreen>
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 67ad5d1..7165218 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -47,7 +47,10 @@
         android:order="3"
         android:title="@string/status_number"
         android:summary="@string/summary_placeholder"
-        android:selectable="false"/>
+        android:selectable="false"
+        settings:allowDynamicSummaryInSlice="true"
+        settings:controller=
+            "com.android.settings.deviceinfo.PhoneNumberPreferenceController" />
 
     <Preference
         android:key="emergency_info"
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 319d599..7b0be94 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -205,7 +205,7 @@
         try {
             final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
             final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
-            final String algOid = pki.getAlgorithmId().getAlgorithm().getId();
+            final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
             final String algName = new AlgorithmId(new ObjectIdentifier(algOid)).getName();
 
             return KeyChain.isBoundKeyAlgorithm(algName);
diff --git a/src/com/android/settings/applications/AppPermissions.java b/src/com/android/settings/applications/AppPermissions.java
deleted file mode 100644
index 6299921..0000000
--- a/src/com/android/settings/applications/AppPermissions.java
+++ /dev/null
@@ -1,169 +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.applications;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionInfo;
-import android.os.Build;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Based off from
- * packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/AppPermissions.java
- * Except we only care about the number rather than the details.
- */
-public final class AppPermissions {
-    private static final String TAG = "AppPermissions";
-
-    private final ArrayMap<String, PermissionGroup> mGroups = new ArrayMap<>();
-    private final Context mContext;
-    private final PackageInfo mPackageInfo;
-
-    public AppPermissions(Context context, String packageName) {
-        mContext = context;
-        mPackageInfo = getPackageInfo(packageName);
-        refresh();
-    }
-
-    private PackageInfo getPackageInfo(String packageName) {
-        try {
-            return mContext.getPackageManager().getPackageInfo(packageName,
-                    PackageManager.GET_PERMISSIONS);
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Unable to find " + packageName, e);
-            return null;
-        }
-    }
-
-    public void refresh() {
-        if (mPackageInfo != null) {
-            loadPermissionGroups();
-        }
-    }
-
-    public int getPermissionCount() {
-        return mGroups.size();
-    }
-
-    public int getGrantedPermissionsCount() {
-        int ct = 0;
-        for (int i = 0; i < mGroups.size(); i++) {
-            if (mGroups.valueAt(i).areRuntimePermissionsGranted()) {
-                ct++;
-            }
-        }
-        return ct;
-    }
-
-    private void loadPermissionGroups() {
-        mGroups.clear();
-        if (mPackageInfo.requestedPermissions == null) {
-            return;
-        }
-
-        final boolean appSupportsRuntimePermissions = appSupportsRuntime(
-                mPackageInfo.applicationInfo);
-
-        for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) {
-            String requestedPerm = mPackageInfo.requestedPermissions[i];
-
-            final PermissionInfo permInfo;
-            try {
-                permInfo = mContext.getPackageManager().getPermissionInfo(requestedPerm, 0);
-            } catch (NameNotFoundException e) {
-                Log.w(TAG, "Unknown permission: " + requestedPerm);
-                continue;
-            }
-
-            String permName = permInfo.name;
-            String groupName = permInfo.group != null ? permInfo.group : permName;
-
-            PermissionGroup group = mGroups.get(groupName);
-            if (group == null) {
-                group = new PermissionGroup();
-                mGroups.put(groupName, group);
-            }
-
-            final boolean runtime = appSupportsRuntimePermissions
-                    && permInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS;
-            final boolean granted = (mPackageInfo.requestedPermissionsFlags[i]
-                    & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
-
-            Permission permission = new Permission(runtime, granted);
-            group.addPermission(permission, permName);
-        }
-        // Only care about runtime perms for now.
-        for (int i = mGroups.size() - 1; i >= 0; i--) {
-            if (!mGroups.valueAt(i).mHasRuntimePermissions) {
-                mGroups.removeAt(i);
-            }
-        }
-    }
-
-    public static boolean appSupportsRuntime(ApplicationInfo info) {
-        return info.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
-    }
-
-    private static final class PermissionGroup {
-        private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>();
-        private boolean mHasRuntimePermissions;
-
-        public boolean hasRuntimePermissions() {
-            return mHasRuntimePermissions;
-        }
-
-        public boolean areRuntimePermissionsGranted() {
-            final int permissionCount = mPermissions.size();
-            for (int i = 0; i < permissionCount; i++) {
-                Permission permission = mPermissions.valueAt(i);
-                if (permission.runtime && !permission.granted) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public List<Permission> getPermissions() {
-            return new ArrayList<>(mPermissions.values());
-        }
-
-        void addPermission(Permission permission, String permName) {
-            mPermissions.put(permName, permission);
-            if (permission.runtime) {
-                mHasRuntimePermissions = true;
-            }
-        }
-    }
-
-    private static final class Permission {
-        private final boolean runtime;
-        private boolean granted;
-
-        public Permission(boolean runtime, boolean granted) {
-            this.runtime = runtime;
-            this.granted = granted;
-        }
-    }
-}
diff --git a/src/com/android/settings/applications/SpecialAppAccessPreferenceController.java b/src/com/android/settings/applications/SpecialAppAccessPreferenceController.java
index a395f98..1763d84 100644
--- a/src/com/android/settings/applications/SpecialAppAccessPreferenceController.java
+++ b/src/com/android/settings/applications/SpecialAppAccessPreferenceController.java
@@ -23,6 +23,7 @@
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.datausage.AppStateDataUsageBridge;
+import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
 import com.android.settings.datausage.DataSaverBackend;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -108,8 +109,8 @@
             if (!ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry)) {
                 continue;
             }
-            if (entry.extraInfo != null && ((AppStateDataUsageBridge.DataUsageState)
-                    entry.extraInfo).isDataSaverWhitelisted) {
+            if (entry.extraInfo instanceof DataUsageState
+                    && ((DataUsageState) entry.extraInfo).isDataSaverWhitelisted) {
                 count++;
             }
         }
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
index 4337b88..9443c93 100644
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
@@ -25,6 +25,7 @@
 import android.os.ServiceManager;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
+import android.util.FeatureFlagUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
@@ -35,6 +36,7 @@
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.datausage.AppDataUsage;
 import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageUtils;
@@ -45,6 +47,12 @@
 import com.android.settingslib.net.ChartData;
 import com.android.settingslib.net.ChartDataLoaderCompat;
 
+/**
+ * Deprecated in favor of {@link AppDataUsagePreferenceControllerV2}
+ *
+ * @deprecated
+ */
+@Deprecated
 public class AppDataUsagePreferenceController extends AppInfoPreferenceControllerBase
         implements LoaderManager.LoaderCallbacks<ChartData>, LifecycleObserver, OnResume, OnPause {
 
@@ -57,6 +65,9 @@
 
     @Override
     public int getAvailabilityStatus() {
+        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
         return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
@@ -93,7 +104,9 @@
 
     @Override
     public void onPause() {
-        mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
+        if (mStatsSession != null) {
+            mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
new file mode 100644
index 0000000..9bbc5c0
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 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.appinfo;
+
+import android.content.Context;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.util.FeatureFlagUtils;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.datausage.AppDataUsageV2;
+import com.android.settings.datausage.DataUsageUtils;
+import com.android.settingslib.AppItem;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
+
+import java.util.List;
+
+public class AppDataUsagePreferenceControllerV2 extends AppInfoPreferenceControllerBase
+        implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
+        OnResume, OnPause {
+
+    private List<NetworkCycleDataForUid> mAppUsageData;
+
+    public AppDataUsagePreferenceControllerV2(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        preference.setSummary(getDataSummary());
+    }
+
+    @Override
+    public void onResume() {
+        if (isAvailable()) {
+            final int uid = mParent.getAppEntry().info.uid;
+            final AppItem app = new AppItem(uid);
+            app.addUid(uid);
+            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
+                    this);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (isAvailable()) {
+            mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
+        }
+    }
+
+    @Override
+    public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+        final NetworkTemplate template = getTemplate(mContext);
+        return NetworkCycleDataForUidLoader.builder(mContext)
+            .setUid(mParent.getAppEntry().info.uid)
+            .setRetrieveDetail(false)
+            .setNetworkTemplate(template)
+            .setSubscriberId(template.getSubscriberId())
+            .build();
+    }
+
+    @Override
+    public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+            List<NetworkCycleDataForUid> data) {
+        mAppUsageData = data;
+        updateState(mPreference);
+    }
+
+    @Override
+    public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+        // Leave last result.
+    }
+
+    @Override
+    protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
+        return AppDataUsageV2.class;
+    }
+
+    private CharSequence getDataSummary() {
+        if (mAppUsageData != null) {
+            long totalBytes = 0;
+            long startTime = System.currentTimeMillis();
+            for (NetworkCycleDataForUid data : mAppUsageData) {
+                totalBytes += data.getTotalUsage();
+                final long cycleStart = data.getStartTime();
+                if (cycleStart < startTime) {
+                    startTime = cycleStart;
+                }
+            }
+            if (totalBytes == 0) {
+                return mContext.getString(R.string.no_data_usage);
+            }
+            return mContext.getString(R.string.data_summary_format,
+                    Formatter.formatFileSize(mContext, totalBytes),
+                    DateUtils.formatDateTime(mContext, startTime,
+                            DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
+        }
+        return mContext.getString(R.string.computing_size);
+    }
+
+    private static NetworkTemplate getTemplate(Context context) {
+        if (DataUsageUtils.hasReadyMobileRadio(context)) {
+            return NetworkTemplate.buildTemplateMobileWildcard();
+        }
+        if (DataUsageUtils.hasWifiRadio(context)) {
+            return NetworkTemplate.buildTemplateWifiWildcard();
+        }
+        return NetworkTemplate.buildTemplateEthernet();
+    }
+
+    @VisibleForTesting
+    boolean isBandwidthControlEnabled() {
+        return Utils.isBandwidthControlEnabled();
+    }
+
+}
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 7b9cc79..64fd36d 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -34,6 +34,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -48,6 +49,7 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.applications.specialaccess.pictureinpicture
         .PictureInPictureDetailPreferenceController;
+import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -139,7 +141,11 @@
         final String packageName = getPackageName();
         use(TimeSpentInAppPreferenceController.class).setPackageName(packageName);
 
-        use(AppDataUsagePreferenceController.class).setParentFragment(this);
+        if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
+            use(AppDataUsagePreferenceControllerV2.class).setParentFragment(this);
+        } else {
+            use(AppDataUsagePreferenceController.class).setParentFragment(this);
+        }
         final AppInstallerInfoPreferenceController installer =
                 use(AppInstallerInfoPreferenceController.class);
         installer.setPackageName(packageName);
diff --git a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
index be41c0f..38e70d1 100644
--- a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
+++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java
@@ -80,21 +80,20 @@
     }
 
     public static CharSequence getPreferenceSummary(Context context, AppEntry entry) {
+        final UserHandle userHandle = UserHandle.getUserHandleForUid(entry.info.uid);
         final UserManager um = UserManager.get(context);
         final int userRestrictionSource = um.getUserRestrictionSource(
-                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
-                UserHandle.getUserHandleForUid(entry.info.uid));
-        switch (userRestrictionSource) {
-            case UserManager.RESTRICTION_SOURCE_DEVICE_OWNER:
-            case UserManager.RESTRICTION_SOURCE_PROFILE_OWNER:
-                return context.getString(R.string.disabled_by_admin);
-            case UserManager.RESTRICTION_SOURCE_SYSTEM:
-                return context.getString(R.string.disabled);
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle)
+                | um.getUserRestrictionSource(
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                        userHandle);
+        if ((userRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
+            return context.getString(R.string.disabled_by_admin);
+        } else if (userRestrictionSource != 0) {
+            return context.getString(R.string.disabled);
         }
-
         final InstallAppsState appsState = new AppStateInstallAppsBridge(context, null, null)
                 .createInstallAppsStateFor(entry.info.packageName, entry.info.uid);
-
         return context.getString(appsState.canInstallApps()
                 ? R.string.app_permission_summary_allowed
                 : R.string.app_permission_summary_not_allowed);
@@ -119,6 +118,10 @@
             return true;
         }
         mSwitchPref.checkRestrictionAndSetDisabled(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+        if (!mSwitchPref.isDisabledByAdmin()) {
+            mSwitchPref.checkRestrictionAndSetDisabled(
+                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
+        }
         if (mSwitchPref.isDisabledByAdmin()) {
             return true;
         }
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index e26f881..9c4f964 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.hardware.face.FaceManager;
-import android.util.Log;
 
+import com.android.settings.Utils;
 import com.android.settings.core.TogglePreferenceController;
 
 import androidx.preference.PreferenceScreen;
@@ -39,7 +39,7 @@
 
     public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
-        mFaceManager = context.getSystemService(FaceManager.class);
+        mFaceManager = Utils.getFaceManagerOrNull(context);
     }
 
     public FaceSettingsAttentionPreferenceController(Context context) {
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
index 297c90b..cac4565 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
@@ -269,8 +269,9 @@
         final BluetoothDevice device = cachedDevice.getDevice();
         if (DBG) {
             Log.d(TAG, "isDeviceConnected() device name : " + cachedDevice.getName() +
-                    ", is connected : " + device.isConnected());
+                    ", is connected : " + device.isConnected() + " , is profile connected : "
+                    + cachedDevice.isConnected());
         }
-        return device.getBondState() == BluetoothDevice.BOND_BONDED && device.isConnected();
+        return device.getBondState() == BluetoothDevice.BOND_BONDED && cachedDevice.isConnected();
     }
 }
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
index 8c6d3f2..127cb03 100644
--- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
@@ -43,9 +43,10 @@
         final BluetoothDevice device = cachedDevice.getDevice();
         if (DBG) {
             Log.d(TAG, "isFilterMatched() device name : " + cachedDevice.getName() +
-                    ", is connected : " + device.isConnected());
+                    ", is connected : " + device.isConnected() + ", is profile connected : "
+                    + cachedDevice.isConnected());
         }
-        return device.getBondState() == BluetoothDevice.BOND_BONDED && !device.isConnected();
+        return device.getBondState() == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected();
     }
 
     @Override
diff --git a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
index 5f6ffb2..ffcd1fc 100644
--- a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.bluetooth.BluetoothDeviceUpdater;
@@ -35,7 +36,9 @@
 public class PreviouslyConnectedDevicePreferenceController extends BasePreferenceController
         implements LifecycleObserver, OnStart, OnStop, DevicePreferenceCallback {
 
-    private Preference mPreference;
+    private static final int MAX_DEVICE_NUM = 3;
+
+    private PreferenceGroup mPreferenceGroup;
     private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
     private DockUpdater mSavedDockUpdater;
     private int mPreferenceSize;
@@ -57,8 +60,10 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
+        mPreferenceGroup = (PreferenceGroup) screen.findPreference(getPreferenceKey());
+        mPreferenceGroup.setVisible(false);
+
         if (isAvailable()) {
-            mPreference = screen.findPreference(getPreferenceKey());
             final Context context = screen.getContext();
             mBluetoothDeviceUpdater.setPrefContext(context);
             mSavedDockUpdater.setPreferenceContext(context);
@@ -69,7 +74,6 @@
     public void onStart() {
         mBluetoothDeviceUpdater.registerCallback();
         mSavedDockUpdater.registerCallback();
-        updatePreferenceOnSizeChanged();
     }
 
     @Override
@@ -86,13 +90,17 @@
     @Override
     public void onDeviceAdded(Preference preference) {
         mPreferenceSize++;
-        updatePreferenceOnSizeChanged();
+        if (mPreferenceSize <= MAX_DEVICE_NUM) {
+            mPreferenceGroup.addPreference(preference);
+        }
+        updatePreferenceVisiblity();
     }
 
     @Override
     public void onDeviceRemoved(Preference preference) {
         mPreferenceSize--;
-        updatePreferenceOnSizeChanged();
+        mPreferenceGroup.removePreference(preference);
+        updatePreferenceVisiblity();
     }
 
     @VisibleForTesting
@@ -106,18 +114,12 @@
     }
 
     @VisibleForTesting
-    void setPreferenceSize(int size) {
-        mPreferenceSize = size;
+    void setPreferenceGroup(PreferenceGroup preferenceGroup) {
+        mPreferenceGroup = preferenceGroup;
     }
 
     @VisibleForTesting
-    void setPreference(Preference preference) {
-        mPreference = preference;
-    }
-
-    private void updatePreferenceOnSizeChanged() {
-        if (isAvailable()) {
-            mPreference.setEnabled(mPreferenceSize != 0);
-        }
+    void updatePreferenceVisiblity() {
+        mPreferenceGroup.setVisible(mPreferenceSize > 0);
     }
 }
diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java
index 6d6089e..4e8325b 100644
--- a/src/com/android/settings/datausage/AppDataUsageV2.java
+++ b/src/com/android/settings/datausage/AppDataUsageV2.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 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
@@ -22,13 +22,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.net.INetworkStatsSession;
-import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
@@ -51,11 +46,13 @@
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
 import com.android.settingslib.net.UidDetail;
 import com.android.settingslib.net.UidDetailProvider;
 
+import java.util.List;
+
 public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenceChangeListener,
         DataSaverBackend.Listener {
 
@@ -73,7 +70,7 @@
     private static final String KEY_CYCLE = "cycle";
     private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
 
-    private static final int LOADER_CHART_DATA = 2;
+    private static final int LOADER_APP_USAGE_DATA = 2;
     private static final int LOADER_APP_PREF = 3;
 
     private PackageManager mPackageManager;
@@ -88,14 +85,10 @@
     private Drawable mIcon;
     private CharSequence mLabel;
     private String mPackageName;
-    private INetworkStatsSession mStatsSession;
     private CycleAdapter mCycleAdapter;
 
-    private long mStart;
-    private long mEnd;
-    private ChartData mChartData;
+    private List<NetworkCycleDataForUid> mUsageData;
     private NetworkTemplate mTemplate;
-    private NetworkPolicy mPolicy;
     private AppItem mAppItem;
     private Intent mAppSettingsIntent;
     private SpinnerPreference mCycle;
@@ -108,12 +101,6 @@
         mPackageManager = getPackageManager();
         final Bundle args = getArguments();
 
-        try {
-            mStatsSession = services.mStatsService.openSession();
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-
         mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
         mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
                 : null;
@@ -209,20 +196,12 @@
     }
 
     @Override
-    public void onDestroy() {
-        TrafficStats.closeQuietly(mStatsSession);
-        super.onDestroy();
-    }
-
-    @Override
     public void onResume() {
         super.onResume();
         if (mDataSaverBackend != null) {
             mDataSaverBackend.addListener(this);
         }
-        mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
-        getLoaderManager().restartLoader(LOADER_CHART_DATA,
-                ChartDataLoaderCompat.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
+        getLoaderManager().restartLoader(LOADER_APP_USAGE_DATA, null /* args */, mUidDataCallbacks);
         updatePrefs();
     }
 
@@ -300,19 +279,17 @@
         }
     }
 
-    private void bindData() {
+    @VisibleForTesting
+    void bindData(int position) {
         final long backgroundBytes, foregroundBytes;
-        if (mChartData == null || mStart == 0) {
+        if (mUsageData == null || position >= mUsageData.size()) {
             backgroundBytes = foregroundBytes = 0;
             mCycle.setVisible(false);
         } else {
             mCycle.setVisible(true);
-            final long now = System.currentTimeMillis();
-            NetworkStatsHistory.Entry entry = null;
-            entry = mChartData.detailDefault.getValues(mStart, mEnd, now, entry);
-            backgroundBytes = entry.rxBytes + entry.txBytes;
-            entry = mChartData.detailForeground.getValues(mStart, mEnd, now, entry);
-            foregroundBytes = entry.rxBytes + entry.txBytes;
+            final NetworkCycleDataForUid data = mUsageData.get(position);
+            backgroundBytes = data.getBackgroudUsage();
+            foregroundBytes = data.getForegroudUsage();
         }
         final long totalBytes = backgroundBytes + foregroundBytes;
         final Context context = getContext();
@@ -376,11 +353,7 @@
             new AdapterView.OnItemSelectedListener() {
         @Override
         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
-
-            mStart = cycle.start;
-            mEnd = cycle.end;
-            bindData();
+            bindData(position);
         }
 
         @Override
@@ -389,24 +362,30 @@
         }
     };
 
-    private final LoaderManager.LoaderCallbacks<ChartData> mChartDataCallbacks =
-            new LoaderManager.LoaderCallbacks<ChartData>() {
-        @Override
-        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
-            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
-        }
+    private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
+        new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
+            @Override
+            public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+                return NetworkCycleDataForUidLoader.builder(getContext())
+                    .setUid(mAppItem.key)
+                    .setRetrieveDetail(true)
+                    .setNetworkTemplate(mTemplate)
+                    .setSubscriberId(mTemplate.getSubscriberId())
+                    .build();
+            }
 
-        @Override
-        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
-            mChartData = data;
-            mCycleAdapter.updateCycleList(mPolicy, mChartData);
-            bindData();
-        }
+            @Override
+            public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+                    List<NetworkCycleDataForUid> data) {
+                mUsageData = data;
+                mCycleAdapter.updateCycleList(data);
+                bindData(0 /* position */);
+            }
 
-        @Override
-        public void onLoaderReset(Loader<ChartData> loader) {
-        }
-    };
+            @Override
+            public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+            }
+        };
 
     private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
         new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
index ea652b3..c6d3b4d 100644
--- a/src/com/android/settings/datausage/DataUsageListV2.java
+++ b/src/com/android/settings/datausage/DataUsageListV2.java
@@ -426,11 +426,11 @@
 
     private void startAppDataUsage(AppItem item) {
         final Bundle args = new Bundle();
-        args.putParcelable(AppDataUsage.ARG_APP_ITEM, item);
-        args.putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, mTemplate);
+        args.putParcelable(AppDataUsageV2.ARG_APP_ITEM, item);
+        args.putParcelable(AppDataUsageV2.ARG_NETWORK_TEMPLATE, mTemplate);
 
         new SubSettingLauncher(getContext())
-                .setDestination(AppDataUsage.class.getName())
+                .setDestination(AppDataUsageV2.class.getName())
                 .setTitleRes(R.string.app_data_usage)
                 .setArguments(args)
                 .setSourceMetricsCategory(getMetricsCategory())
@@ -490,8 +490,6 @@
         @Override
         public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
             return NetworkCycleChartDataLoader.builder(getContext())
-                    .setNetworkPolicy(services.mPolicyEditor.getPolicy(mTemplate))
-                    .setNetworkType(mNetworkType)
                     .setNetworkTemplate(mTemplate)
                     .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
                     .build();
diff --git a/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java b/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
index 233111a..a819f10 100644
--- a/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
+++ b/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
@@ -17,10 +17,10 @@
 package com.android.settings.datetime.timezone;
 
 import android.content.Context;
-import android.icu.impl.OlsonTimeZone;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
 import android.icu.text.SimpleDateFormat;
+import android.icu.util.BasicTimeZone;
 import android.icu.util.Calendar;
 import android.icu.util.TimeZone;
 import android.icu.util.TimeZoneTransition;
@@ -115,17 +115,17 @@
     }
 
     private TimeZoneTransition findNextDstTransition(TimeZone timeZone) {
-        if (!(timeZone instanceof OlsonTimeZone)) {
+        if (!(timeZone instanceof BasicTimeZone)) {
             return null;
         }
-        final OlsonTimeZone olsonTimeZone = (OlsonTimeZone) timeZone;
-        TimeZoneTransition transition = olsonTimeZone.getNextTransition(
+        final BasicTimeZone basicTimeZone = (BasicTimeZone) timeZone;
+        TimeZoneTransition transition = basicTimeZone.getNextTransition(
                 mDate.getTime(), /* inclusive */ false);
         do {
             if (transition.getTo().getDSTSavings() != transition.getFrom().getDSTSavings()) {
                 break;
             }
-            transition = olsonTimeZone.getNextTransition(
+            transition = basicTimeZone.getNextTransition(
                     transition.getTime(), /*inclusive */ false);
         } while (transition != null);
         return transition;
diff --git a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java
index 7670ef1..d27af64 100644
--- a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java
+++ b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java
@@ -23,6 +23,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settings.core.FeatureFlags;
 
 import java.util.HashSet;
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index 8e60b06..6f5f346 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -29,15 +29,13 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.DeviceInfoUtils;
-import com.android.settingslib.core.AbstractPreferenceController;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class PhoneNumberPreferenceController extends AbstractPreferenceController implements
-        PreferenceControllerMixin {
+public class PhoneNumberPreferenceController extends BasePreferenceController {
 
     private final static String KEY_PHONE_NUMBER = "phone_number";
 
@@ -45,21 +43,20 @@
     private final SubscriptionManager mSubscriptionManager;
     private final List<Preference> mPreferenceList = new ArrayList<>();
 
-    public PhoneNumberPreferenceController(Context context) {
-        super(context);
-        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        mSubscriptionManager = (SubscriptionManager) context.getSystemService(
-                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+    public PhoneNumberPreferenceController(Context context, String key) {
+        super(context, key);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+        mSubscriptionManager =  mContext.getSystemService(SubscriptionManager.class);
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_PHONE_NUMBER;
+    public int getAvailabilityStatus() {
+        return mTelephonyManager.isVoiceCapable() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
-    public boolean isAvailable() {
-        return mTelephonyManager.isVoiceCapable();
+    public CharSequence getSummary() {
+        return getFirstPhoneNumber();
     }
 
     @Override
@@ -89,10 +86,26 @@
         }
     }
 
+    @Override
+    public boolean isSliceable() {
+        return true;
+    }
+
+    private CharSequence getFirstPhoneNumber() {
+        final List<SubscriptionInfo> subscriptionInfoList =
+                mSubscriptionManager.getActiveSubscriptionInfoList();
+        if (subscriptionInfoList == null) {
+            return mContext.getText(R.string.device_info_default);
+        }
+
+        // For now, We only return first result for slice view.
+        return getFormattedPhoneNumber(subscriptionInfoList.get(0));
+    }
+
     private CharSequence getPhoneNumber(int simSlot) {
         final SubscriptionInfo subscriptionInfo = getSubscriptionInfo(simSlot);
         if (subscriptionInfo == null) {
-            return mContext.getString(R.string.device_info_default);
+            return mContext.getText(R.string.device_info_default);
         }
 
         return getFormattedPhoneNumber(subscriptionInfo);
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 5503ea9..37f80b7 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -41,7 +41,6 @@
 import com.android.settings.deviceinfo.FeedbackPreferenceController;
 import com.android.settings.deviceinfo.IpAddressPreferenceController;
 import com.android.settings.deviceinfo.ManualPreferenceController;
-import com.android.settings.deviceinfo.PhoneNumberPreferenceController;
 import com.android.settings.deviceinfo.RegulatoryInfoPreferenceController;
 import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
 import com.android.settings.deviceinfo.UptimePreferenceController;
@@ -110,7 +109,6 @@
             Lifecycle lifecycle) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new EmergencyInfoPreferenceController(context));
-        controllers.add(new PhoneNumberPreferenceController(context));
         controllers.add(new BrandedAccountPreferenceController(context));
         DeviceNamePreferenceController deviceNamePreferenceController =
                 new DeviceNamePreferenceController(context);
diff --git a/src/com/android/settings/homepage/CardContentProvider.java b/src/com/android/settings/homepage/CardContentProvider.java
index 7b08756..9989445 100644
--- a/src/com/android/settings/homepage/CardContentProvider.java
+++ b/src/com/android/settings/homepage/CardContentProvider.java
@@ -77,8 +77,11 @@
 
             final String table = getTableFromMatch(uri);
             database.beginTransaction();
+
+            // Here deletion first is avoiding redundant insertion. According to cl/215350754
+            database.delete(table, null /* whereClause */, null /* whereArgs */);
             for (ContentValues value : values) {
-                long ret = database.insert(table, null, value);
+                long ret = database.insert(table, null /* nullColumnHack */, value);
                 if (ret != -1L) {
                     numInserted++;
                 } else {
@@ -87,7 +90,7 @@
                 }
             }
             database.setTransactionSuccessful();
-            getContext().getContentResolver().notifyChange(uri, null);
+            getContext().getContentResolver().notifyChange(uri, null /* observer */);
         } finally {
             database.endTransaction();
             StrictMode.setThreadPolicy(oldPolicy);
@@ -103,7 +106,7 @@
             final SQLiteDatabase database = mDBHelper.getWritableDatabase();
             final String table = getTableFromMatch(uri);
             final int rowsDeleted = database.delete(table, selection, selectionArgs);
-            getContext().getContentResolver().notifyChange(uri, null);
+            getContext().getContentResolver().notifyChange(uri, null /* observer */);
             return rowsDeleted;
         } finally {
             StrictMode.setThreadPolicy(oldPolicy);
@@ -127,7 +130,8 @@
             queryBuilder.setTables(table);
             final SQLiteDatabase database = mDBHelper.getReadableDatabase();
             final Cursor cursor = queryBuilder.query(database,
-                    projection, selection, selectionArgs, null, null, sortOrder);
+                    projection, selection, selectionArgs, null /* groupBy */, null /* having */,
+                    sortOrder);
 
             cursor.setNotificationUri(getContext().getContentResolver(), uri);
             return cursor;
@@ -145,7 +149,7 @@
             final SQLiteDatabase database = mDBHelper.getWritableDatabase();
             final String table = getTableFromMatch(uri);
             final int rowsUpdated = database.update(table, values, selection, selectionArgs);
-            getContext().getContentResolver().notifyChange(uri, null);
+            getContext().getContentResolver().notifyChange(uri, null /* observer */);
             return rowsUpdated;
         } finally {
             StrictMode.setThreadPolicy(oldPolicy);
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
new file mode 100644
index 0000000..44705c5
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 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.homepage.contextualcards;
+
+import static android.provider.SettingsSlicesContract.KEY_WIFI;
+
+import android.annotation.Nullable;
+
+import com.android.settings.homepage.deviceinfo.DataUsageSlice;
+import com.android.settings.wifi.WifiSlice;
+
+import com.google.android.settings.intelligence.libs.contextualcards.ContextualCard;
+import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Provides dynamic card for SettingsIntelligence. */
+public class SettingsContextualCardProvider extends ContextualCardProvider {
+
+    public static final String CARD_AUTHORITY = "com.android.settings.homepage.contextualcards";
+
+    @Override
+    @Nullable
+    public List<ContextualCard> getContextualCards() {
+        final List<ContextualCard> cards = new ArrayList<>();
+        final ContextualCard wifiCard =
+                new ContextualCard.Builder()
+                        .setSliceUri(WifiSlice.WIFI_URI.toString())
+                        .setName(KEY_WIFI)
+                        .build();
+        final ContextualCard dataUsageCard =
+                new ContextualCard.Builder()
+                        .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI.toString())
+                        .setName(DataUsageSlice.PATH_DATA_USAGE_CARD)
+                        .build();
+
+        cards.add(wifiCard);
+        cards.add(dataUsageCard);
+        return cards;
+    }
+}
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 6b99e1f..633fc45 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -231,9 +231,13 @@
 
         final Intent intent = getIntent();
         final String action = intent.getAction();
+        if (TextUtils.isEmpty(action)) {
+            finish();
+            return;
+        }
+
         mSubId = intent.getIntExtra(ApnSettings.SUB_ID,
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-
         mReadOnlyApn = false;
         mReadOnlyApnTypes = null;
         mReadOnlyApnFields = null;
diff --git a/src/com/android/settings/notification/BlockPreferenceController.java b/src/com/android/settings/notification/BlockPreferenceController.java
index 9e4c463..bee32f5 100644
--- a/src/com/android/settings/notification/BlockPreferenceController.java
+++ b/src/com/android/settings/notification/BlockPreferenceController.java
@@ -65,6 +65,7 @@
 
     public void updateState(Preference preference) {
         LayoutPreference pref = (LayoutPreference) preference;
+        pref.setSelectable(false);
         SwitchBar bar = pref.findViewById(R.id.switch_bar);
         if (bar != null) {
             bar.setSwitchBarText(R.string.notification_switch_label,
diff --git a/src/com/android/settings/notification/ZenDeleteRuleDialog.java b/src/com/android/settings/notification/ZenDeleteRuleDialog.java
index ea582d1..804196e 100644
--- a/src/com/android/settings/notification/ZenDeleteRuleDialog.java
+++ b/src/com/android/settings/notification/ZenDeleteRuleDialog.java
@@ -19,15 +19,16 @@
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
+import android.text.BidiFormatter;
 import android.view.View;
 
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.Fragment;
-
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+
 public class ZenDeleteRuleDialog extends InstrumentedDialogFragment {
     protected static final String TAG = "ZenDeleteRuleDialog";
     private static final String EXTRA_ZEN_RULE_NAME = "zen_rule_name";
@@ -43,8 +44,9 @@
 
     public static void show(Fragment parent, String ruleName, String id, PositiveClickListener
             listener) {
+        final BidiFormatter bidi = BidiFormatter.getInstance();
         final Bundle args = new Bundle();
-        args.putString(EXTRA_ZEN_RULE_NAME, ruleName);
+        args.putString(EXTRA_ZEN_RULE_NAME, bidi.unicodeWrap(ruleName));
         args.putString(EXTRA_ZEN_RULE_ID, id);
         mPositiveClickListener = listener;
 
diff --git a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
index b642915..694625e 100644
--- a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java
@@ -94,4 +94,22 @@
                 .isEqualTo(mContext.getResources().getQuantityString(
                         R.plurals.special_access_summary, 1, 1));
     }
+
+    @Test
+    public void updateState_wrongExtraInfo_shouldNotIncludeInSummary() {
+        final ArrayList<ApplicationsState.AppEntry> apps = new ArrayList<>();
+        final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+        entry.hasLauncherEntry = true;
+        entry.info = new ApplicationInfo();
+        entry.extraInfo = new AppStateNotificationBridge.NotificationsSentState();
+        apps.add(entry);
+        when(mSession.getAllApps()).thenReturn(apps);
+
+        mController.displayPreference(mScreen);
+        mController.onExtraInfoUpdated();
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getResources().getQuantityString(
+                        R.plurals.special_access_summary, 0, 0));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
index 74966a2..e77106d 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
@@ -115,6 +115,7 @@
 
     @Test
     public void onPause_shouldDestroyDataLoader() {
+        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
 
         mController.onPause();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
new file mode 100644
index 0000000..5e9179f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 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.appinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.net.ConnectivityManager;
+import android.os.Bundle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.datausage.AppDataUsageV2;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;import android.net.INetworkStatsSession;
+import android.util.FeatureFlagUtils;
+
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import androidx.loader.app.LoaderManager;
+import androidx.preference.Preference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AppDataUsagePreferenceControllerV2Test {
+
+    @Mock
+    private LoaderManager mLoaderManager;
+    @Mock
+    private AppInfoDashboardFragment mFragment;
+
+    private Context mContext;
+    private AppDataUsagePreferenceControllerV2 mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
+        mController = spy(new AppDataUsagePreferenceControllerV2(mContext, "test_key"));
+        mController.setParentFragment(mFragment);
+        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
+    }
+
+    @Test
+    public void getAvailabilityStatus_bandwidthControlEnabled_shouldReturnAvailable() {
+        doReturn(true).when(mController).isBandwidthControlEnabled();
+
+        assertThat(mController.getAvailabilityStatus())
+            .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_bandwidthControlDisabled_shouldReturnDisabled() {
+        doReturn(false).when(mController).isBandwidthControlEnabled();
+
+        assertThat(mController.getAvailabilityStatus())
+            .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void onResume_notAvailable_shouldNotRestartDataLoader() {
+        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, false);
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+        mController.onResume();
+
+        verify(mLoaderManager, never()).restartLoader(
+                AppInfoDashboardFragment.LOADER_CHART_DATA, Bundle.EMPTY, mController);
+    }
+
+    @Test
+    public void onResume_isAvailable_shouldRestartDataLoader() {
+        final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
+        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+                .thenReturn(connectivityManager);
+        when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
+        final AppEntry appEntry = mock(AppEntry.class);
+        appEntry.info = new ApplicationInfo();
+        when(mFragment.getAppEntry()).thenReturn(appEntry);
+
+        mController.onResume();
+
+        verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
+                nullable(Bundle.class), eq(mController));
+    }
+
+    @Test
+    public void onPause_shouldDestroyDataLoader() {
+        doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+        mController.onPause();
+
+        verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_CHART_DATA);
+    }
+
+    @Test
+    public void getDetailFragmentClass_shouldReturnAppDataUsage() {
+        assertThat(mController.getDetailFragmentClass()).isEqualTo(AppDataUsageV2.class);
+    }
+
+    @Test
+    public void updateState_shouldUpdatePreferenceSummary() {
+        final Preference preference = mock(Preference.class);
+
+        mController.updateState(preference);
+
+        verify(preference).setSummary(any());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java
index d636fa4..e625eee 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java
@@ -17,29 +17,36 @@
 package com.android.settings.applications.appinfo;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.os.UserHandle;
 import android.os.UserManager;
-
 import com.android.settings.applications.AppStateInstallAppsBridge;
 import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
+import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedPreferenceHelper;
 import com.android.settingslib.RestrictedSwitchPreference;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowUserManager.class})
 public class ExternalSourcesDetailsTest {
 
     @Mock
@@ -47,6 +54,8 @@
     @Mock
     private RestrictedSwitchPreference mSwitchPref;
     @Mock
+    private RestrictedPreferenceHelper mHelper;
+    @Mock
     private PackageInfo mPackageInfo;
 
     private ExternalSourcesDetails mFragment;
@@ -90,5 +99,128 @@
         mFragment.refreshUi();
 
         assertThat(mFragment.refreshUi()).isTrue();
+        assertThat(mSwitchPref.isDisabledByAdmin()).isFalse();
+    }
+
+    @Test
+    public void refreshUi_userRestrictionsUnknownSources_disablesSwitchPreference() {
+        // Mocks set up
+        final ExternalSourcesDetails fragment = new ExternalSourcesDetails();
+        final ContextWrapper context = RuntimeEnvironment.application;
+        final UserManager userManager = (UserManager) context.getSystemService(
+                Context.USER_SERVICE);
+        final ShadowUserManager shadowUserManager = Shadow.extract(userManager);
+
+        ReflectionHelpers.setField(fragment, "mSwitchPref", mSwitchPref);
+        ReflectionHelpers.setField(fragment, "mPackageInfo", mPackageInfo);
+        mPackageInfo.applicationInfo = new ApplicationInfo();
+        ReflectionHelpers.setField(fragment, "mUserManager", userManager);
+        ReflectionHelpers.setField(mSwitchPref, "mHelper", mHelper);
+
+        final AppStateInstallAppsBridge appBridge = mock(AppStateInstallAppsBridge.class);
+        ReflectionHelpers.setField(fragment, "mAppBridge", appBridge);
+        when(appBridge.createInstallAppsStateFor(nullable(String.class), anyInt()))
+                .thenReturn(mock(InstallAppsState.class));
+
+        // Test restriction set up
+        shadowUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+        doAnswer((answer) -> {
+            when(mSwitchPref.isDisabledByAdmin()).thenReturn(true);
+            return null;
+        }).when(mSwitchPref).checkRestrictionAndSetDisabled(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+
+        // Code execution
+        assertThat(fragment.refreshUi()).isTrue();
+
+        // Assertions
+        assertThat(shadowUserManager.hasUserRestriction(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                UserHandle.of(UserHandle.myUserId()))).isTrue();
+        assertThat(mSwitchPref.isDisabledByAdmin()).isTrue();
+    }
+
+    @Test
+    public void refreshUi_userRestrictionsUnknownSourcesGlobally_disablesSwitchPreference() {
+        // Mocks set up
+        final ExternalSourcesDetails fragment = new ExternalSourcesDetails();
+        final ContextWrapper context = RuntimeEnvironment.application;
+        final UserManager userManager = (UserManager) context.getSystemService(
+                Context.USER_SERVICE);
+        final ShadowUserManager shadowUserManager = Shadow.extract(userManager);
+
+        ReflectionHelpers.setField(fragment, "mSwitchPref", mSwitchPref);
+        ReflectionHelpers.setField(fragment, "mPackageInfo", mPackageInfo);
+        mPackageInfo.applicationInfo = new ApplicationInfo();
+        ReflectionHelpers.setField(fragment, "mUserManager", userManager);
+        ReflectionHelpers.setField(mSwitchPref, "mHelper", mHelper);
+
+        final AppStateInstallAppsBridge appBridge = mock(AppStateInstallAppsBridge.class);
+        ReflectionHelpers.setField(fragment, "mAppBridge", appBridge);
+        when(appBridge.createInstallAppsStateFor(nullable(String.class), anyInt()))
+                .thenReturn(mock(InstallAppsState.class));
+
+        // Test restriction set up
+        shadowUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, true);
+        doAnswer((answer) -> {
+            when(mSwitchPref.isDisabledByAdmin()).thenReturn(true);
+            return null;
+        }).when(mSwitchPref).checkRestrictionAndSetDisabled(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
+
+        // Code execution
+        assertThat(fragment.refreshUi()).isTrue();
+
+        // Assertions
+        assertThat(shadowUserManager.hasUserRestriction(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                UserHandle.of(UserHandle.myUserId()))).isTrue();
+        assertThat(mSwitchPref.isDisabledByAdmin()).isTrue();
+    }
+
+    @Test
+    public void refreshUi_bothUnknownSourcesUserRestrictions_disableSwitchPreference() {
+        // Mocks set up
+        final ExternalSourcesDetails fragment = new ExternalSourcesDetails();
+        final ContextWrapper context = RuntimeEnvironment.application;
+        final UserManager userManager = (UserManager) context.getSystemService(
+                Context.USER_SERVICE);
+        final ShadowUserManager shadowUserManager = Shadow.extract(userManager);
+
+        ReflectionHelpers.setField(fragment, "mSwitchPref", mSwitchPref);
+        ReflectionHelpers.setField(fragment, "mPackageInfo", mPackageInfo);
+        mPackageInfo.applicationInfo = new ApplicationInfo();
+        ReflectionHelpers.setField(fragment, "mUserManager", userManager);
+        ReflectionHelpers.setField(mSwitchPref, "mHelper", mHelper);
+
+        final AppStateInstallAppsBridge appBridge = mock(AppStateInstallAppsBridge.class);
+        ReflectionHelpers.setField(fragment, "mAppBridge", appBridge);
+        when(appBridge.createInstallAppsStateFor(nullable(String.class), anyInt()))
+                .thenReturn(mock(InstallAppsState.class));
+
+        // Test restriction set up
+        shadowUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, true);
+        shadowUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+        doAnswer((answer) -> {
+            when(mSwitchPref.isDisabledByAdmin()).thenReturn(true);
+            return null;
+        }).when(mSwitchPref).checkRestrictionAndSetDisabled(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
+
+        // Code execution
+        assertThat(fragment.refreshUi()).isTrue();
+
+        // Assertions
+        assertThat(shadowUserManager.hasUserRestriction(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                UserHandle.of(UserHandle.myUserId()))).isTrue();
+        assertThat(shadowUserManager.hasUserRestriction(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                UserHandle.of(UserHandle.myUserId()))).isTrue();
+        assertThat(mSwitchPref.isDisabledByAdmin()).isTrue();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
index 28bf3ab..4ede947 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
@@ -161,7 +161,7 @@
     @Test
     public void isDeviceConnected_deviceConnected() {
         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
-        doReturn(true).when(mBluetoothDevice).isConnected();
+        doReturn(true).when(mCachedBluetoothDevice).isConnected();
 
         assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isTrue();
     }
@@ -169,7 +169,7 @@
     @Test
     public void isDeviceConnected_deviceNotConnected() {
         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
-        doReturn(false).when(mBluetoothDevice).isConnected();
+        doReturn(false).when(mCachedBluetoothDevice).isConnected();
 
         assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
index e25e4b2..4d4a711 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
@@ -77,7 +77,7 @@
     @Test
     public void update_filterMatch_addPreference() {
         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
-        doReturn(false).when(mBluetoothDevice).isConnected();
+        doReturn(false).when(mCachedBluetoothDevice).isConnected();
 
         mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
 
@@ -87,7 +87,7 @@
     @Test
     public void update_filterNotMatch_removePreference() {
         doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState();
-        doReturn(true).when(mBluetoothDevice).isConnected();
+        doReturn(true).when(mCachedBluetoothDevice).isConnected();
 
         mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
 
@@ -96,7 +96,7 @@
 
     @Test
     public void onProfileConnectionStateChanged_deviceConnected_removePreference() {
-        when(mBluetoothDevice.isConnected()).thenReturn(true);
+        when(mCachedBluetoothDevice.isConnected()).thenReturn(true);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
@@ -106,7 +106,7 @@
 
     @Test
     public void onProfileConnectionStateChanged_deviceDisconnected_addPreference() {
-        when(mBluetoothDevice.isConnected()).thenReturn(false);
+        when(mCachedBluetoothDevice.isConnected()).thenReturn(false);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
index fc08016..52b2e95 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
@@ -28,6 +28,9 @@
 import android.content.pm.PackageManager;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceManager;
 
 import com.android.settings.bluetooth.BluetoothDeviceUpdater;
 import com.android.settings.connecteddevice.dock.DockUpdater;
@@ -54,10 +57,12 @@
     private DockUpdater mDockUpdater;
     @Mock
     private PackageManager mPackageManager;
+    @Mock
+    private PreferenceManager mPreferenceManager;
 
     private Context mContext;
     private PreviouslyConnectedDevicePreferenceController mPreConnectedDeviceController;
-    private Preference mPreference;
+    private PreferenceGroup mPreferenceGroup;
 
     @Before
     public void setUp() {
@@ -70,8 +75,10 @@
         mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
         mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater);
 
-        mPreference = new Preference(mContext);
-        mPreConnectedDeviceController.setPreference(mPreference);
+        mPreferenceGroup = spy(new PreferenceCategory(mContext));
+        doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager();
+        mPreferenceGroup.setVisible(false);
+        mPreConnectedDeviceController.setPreferenceGroup(mPreferenceGroup);
     }
 
     @Test
@@ -101,20 +108,34 @@
     }
 
     @Test
-    public void onDeviceAdded_addFirstDevice_preferenceIsEnable() {
-        doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-        mPreConnectedDeviceController.setPreferenceSize(0);
-        mPreConnectedDeviceController.onDeviceAdded(mPreference);
+    public void onDeviceAdded_addDevicePreference_displayIt() {
+        mPreConnectedDeviceController.onDeviceAdded(new Preference(mContext));
 
-        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreferenceGroup.isVisible()).isTrue();
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
     }
 
     @Test
-    public void onDeviceRemoved_removeLastDevice_preferenceIsDisable() {
-        doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
-        mPreConnectedDeviceController.setPreferenceSize(1);
-        mPreConnectedDeviceController.onDeviceRemoved(mPreference);
+    public void onDeviceAdded_addFourDevicePreference_onlyDisplayThree() {
+        mPreConnectedDeviceController.onDeviceAdded(new Preference(mContext));
+        mPreConnectedDeviceController.onDeviceAdded(new Preference(mContext));
+        mPreConnectedDeviceController.onDeviceAdded(new Preference(mContext));
+        mPreConnectedDeviceController.onDeviceAdded(new Preference(mContext));
 
-        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreferenceGroup.isVisible()).isTrue();
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(3);
     }
+
+    @Test
+    public void onDeviceRemoved_removeLastDevice_setInvisible() {
+        final Preference preference = new Preference(mContext);
+        mPreferenceGroup.addPreference(preference);
+        mPreferenceGroup.setVisible(true);
+
+        mPreConnectedDeviceController.onDeviceRemoved(preference);
+
+        assertThat(mPreferenceGroup.isVisible()).isFalse();
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
index d979b68..8796a39 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
@@ -19,6 +19,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doNothing;
@@ -28,12 +29,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkPolicyManager;
 import android.os.Bundle;
 import android.util.ArraySet;
 import android.view.View;
 
+import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 
@@ -45,6 +48,7 @@
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.net.NetworkCycleDataForUid;
 
 import org.junit.After;
 import org.junit.Before;
@@ -57,6 +61,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
 public class AppDataUsageV2Test {
@@ -172,4 +179,49 @@
         verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
         verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
     }
+
+    @Test
+    public void bindData_noAppUsageData_shouldHideCycleSpinner() {
+        mFragment = spy(new AppDataUsageV2());
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+        final Preference preference = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
+        doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(false);
+    }
+
+    @Test
+    public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
+        mFragment = spy(new AppDataUsageV2());
+        final Context context = RuntimeEnvironment.application;
+        doReturn(context).when(mFragment).getContext();
+        final long backgroundBytes = 1234L;
+        final long foregroundBytes = 5678L;
+        final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
+        appUsage.add(new NetworkCycleDataForUid.Builder()
+            .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
+        ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
+        final Preference backgroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
+        final Preference foregroundPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
+        final Preference totalPref = mock(Preference.class);
+        ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
+        final SpinnerPreference cycle = mock(SpinnerPreference.class);
+        ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+
+        mFragment.bindData(0 /* position */);
+
+        verify(cycle).setVisible(true);
+        verify(totalPref).setSummary(
+            DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
+        verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
+        verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 4748135..82056a2 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -16,8 +16,7 @@
 
 package com.android.settings.deviceinfo;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
@@ -27,12 +26,14 @@
 
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -41,7 +42,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class PhoneNumberPreferenceControllerTest {
@@ -55,6 +55,8 @@
     @Mock
     private SubscriptionInfo mSubscriptionInfo;
     @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
     private PreferenceScreen mScreen;
 
     private Context mContext;
@@ -63,9 +65,10 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = spy(new PhoneNumberPreferenceController(mContext));
-        ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        mController = spy(new PhoneNumberPreferenceController(mContext, "phone_number"));
         final String prefKey = mController.getPreferenceKey();
         when(mScreen.findPreference(prefKey)).thenReturn(mPreference);
         when(mScreen.getContext()).thenReturn(mContext);
@@ -75,17 +78,19 @@
     }
 
     @Test
-    public void isAvailable_shouldBeTrueIfCallCapable() {
+    public void getAvailabilityStatus_isVoiceCapable_shouldBeAVAILABLE() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
 
-        assertTrue(mController.isAvailable());
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
     }
 
     @Test
-    public void isAvailable_shouldBeFalseIfNotCallCapable() {
+    public void getAvailabilityStatus_isNotVoiceCapable_shouldBeUNSUPPORTED_ON_DEVICE() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
 
-        assertFalse(mController.isAvailable());
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
@@ -126,4 +131,19 @@
                 mContext.getString(R.string.status_number_sim_slot, 2 /* sim slot */));
         verify(mSecondPreference).setSummary(phoneNumber);
     }
+
+    @Test
+    public void getSummary_cannotGetActiveSubscriptionInfo_shouldShowUnknown() {
+        when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
+
+        CharSequence primaryNumber = mController.getSummary();
+
+        assertThat(primaryNumber).isNotNull();
+        assertThat(primaryNumber).isEqualTo(mContext.getString(R.string.device_info_default));
+    }
+
+    @Test
+    public void isSliceable_shouldBeTrue() {
+        assertThat(mController.isSliceable()).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
new file mode 100644
index 0000000..80d9497
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.homepage.contextualcards;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.android.settings.intelligence.libs.contextualcards.ContextualCard;
+import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SettingsContextualCardProviderTest {
+
+    private Context mContext;
+    private ContentResolver mResolver;
+    private Uri mUri;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mResolver = mContext.getContentResolver();
+        mUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsContextualCardProvider.CARD_AUTHORITY)
+                .build();
+    }
+
+    @Test
+    public void contentProviderCall_returnCorrectSize() {
+        final Bundle returnValue =
+                mResolver.call(mUri, ContextualCardProvider.METHOD_GET_CARD_LIST, "", null);
+        final ArrayList<ContextualCard> cards =
+                returnValue.getParcelableArrayList(ContextualCardProvider.BUNDLE_CARD_LIST);
+        assertThat(cards.size()).isEqualTo(2);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index cc480c3..b6242c3 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -19,11 +19,13 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -450,6 +452,15 @@
         assertThat(ApnEditor.formatInteger("not an int")).isEqualTo("not an int");
     }
 
+    @Test
+    public void onCreate_noAction_shouldFinishAndNoCrash() {
+        doNothing().when(mApnEditorUT).addPreferencesFromResource(anyInt());
+
+        mApnEditorUT.onCreate(null);
+
+        verify(mApnEditorUT).finish();
+    }
+
     private void initCursor() {
         doReturn(2).when(mCursor).getColumnCount();
         doReturn(Integer.valueOf(2)).when(mCursor).getInt(CURSOR_INTEGER_INDEX);