Merge "Check instance before casting"
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..90a46ae 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]-->
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/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
index 4337b88..8eb2dfc 100644
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
@@ -45,6 +45,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 {
 
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..8e318bd
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import android.content.Context;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+
+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.datausage.AppDataUsage;
+import com.android.settings.datausage.DataUsageList;
+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.ChartData;
+import com.android.settingslib.net.ChartDataLoaderCompat;
+
+public class AppDataUsagePreferenceControllerV2 extends AppInfoPreferenceControllerBase
+        implements LoaderManager.LoaderCallbacks<ChartData>, LifecycleObserver, OnResume, OnPause {
+
+    private ChartData mChartData;
+    private INetworkStatsSession mStatsSession;
+
+    public AppDataUsagePreferenceControllerV2(Context context,String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+            try {
+                mStatsSession = statsService.openSession();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        preference.setSummary(getDataSummary());
+    }
+
+    @Override
+    public void onResume() {
+        if (mStatsSession != null) {
+            final int uid = mParent.getAppEntry().info.uid;
+            final AppItem app = new AppItem(uid);
+            app.addUid(uid);
+            mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA,
+                    ChartDataLoaderCompat.buildArgs(getTemplate(mContext), app),
+                    this);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
+    }
+
+    @Override
+    public Loader<ChartData> onCreateLoader(int id, Bundle args) {
+        return new ChartDataLoaderCompat(mContext, mStatsSession, args);
+    }
+
+    @Override
+    public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+        mChartData = data;
+        updateState(mPreference);
+    }
+
+    @Override
+    public void onLoaderReset(Loader<ChartData> loader) {
+        // Leave last result.
+    }
+
+    @Override
+    protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
+        return AppDataUsage.class;
+    }
+
+    private CharSequence getDataSummary() {
+        if (mChartData != null) {
+            final long totalBytes = mChartData.detail.getTotalBytes();
+            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, mChartData.detail.getStart(),
+                            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/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/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/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/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/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
new file mode 100644
index 0000000..0023250
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
@@ -0,0 +1,138 @@
+/*
+ * 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.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.net.INetworkStatsSession;
+import android.os.Bundle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.datausage.AppDataUsage;
+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 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);
+    }
+
+    @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_noSession_shouldNotRestartDataLoader() {
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+        mController.onResume();
+
+        verify(mLoaderManager, never()).restartLoader(
+                AppInfoDashboardFragment.LOADER_CHART_DATA, Bundle.EMPTY, mController);
+    }
+
+    @Test
+    public void onResume_hasSession_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();
+        ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+        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), any(Bundle.class), eq(mController));
+    }
+
+    @Test
+    public void onPause_shouldDestroyDataLoader() {
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+        mController.onPause();
+
+        verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_CHART_DATA);
+    }
+
+    @Test
+    public void getDetailFragmentClass_shouldReturnAppDataUsage() {
+        assertThat(mController.getDetailFragmentClass()).isEqualTo(AppDataUsage.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/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);