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