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);