diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a5586f7955e..e42715f7d1e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -788,7 +788,7 @@ diff --git a/res/drawable/ic_suggestion_wallpaper.xml b/res/drawable/ic_suggestion_wallpaper.xml deleted file mode 100644 index 32defcecdc1..00000000000 --- a/res/drawable/ic_suggestion_wallpaper.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - diff --git a/res/layout/manage_applications_apps_unsupported.xml b/res/layout/manage_applications_apps_unsupported.xml new file mode 100644 index 00000000000..d7c6726e377 --- /dev/null +++ b/res/layout/manage_applications_apps_unsupported.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 90b72e16395..1058c2825ec 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10183,6 +10183,10 @@ This feature is not available on this device + + This feature is not available + + It will slow down this phone Force full GNSS measurements diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml index 9cb73a2ea6b..da103c57bf4 100644 --- a/res/xml/accessibility_settings.xml +++ b/res/xml/accessibility_settings.xml @@ -58,6 +58,14 @@ android:title="@string/screen_zoom_title" settings:searchable="false"/> + + + android:fragment="com.android.settings.applications.manageapplications.ManageApplications" + settings:controller="com.android.settings.applications.AllAppsInfoPreferenceController"/> + settings:keywords="@string/keywords_system_alert_window" + settings:controller="com.android.settings.applications.specialaccess.SystemAlertWindowPreferenceController"> diff --git a/src/com/android/settings/CryptKeeperConfirm.java b/src/com/android/settings/CryptKeeperConfirm.java index 248494877d3..49d027ba492 100644 --- a/src/com/android/settings/CryptKeeperConfirm.java +++ b/src/com/android/settings/CryptKeeperConfirm.java @@ -38,6 +38,7 @@ import android.widget.Button; import com.android.internal.widget.LockPatternUtils; import com.android.settings.core.InstrumentedFragment; +import java.util.Arrays; import java.util.Locale; public class CryptKeeperConfirm extends InstrumentedFragment { @@ -87,7 +88,12 @@ public class CryptKeeperConfirm extends InstrumentedFragment { IStorageManager storageManager = IStorageManager.Stub.asInterface(service); try { Bundle args = getIntent().getExtras(); - storageManager.encryptStorage(args.getInt("type", -1), args.getString("password")); + // TODO(b/120484642): Update vold to accept a password as a byte array + byte[] passwordBytes = args.getByteArray("password"); + String password = passwordBytes != null ? new String(passwordBytes) : null; + Arrays.fill(passwordBytes, (byte) 0); + storageManager.encryptStorage(args.getInt("type", -1), + password); } catch (Exception e) { Log.e("CryptKeeper", "Error while encrypting...", e); } diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 804c7830d20..69b8c569a60 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -55,6 +55,7 @@ import android.net.LinkProperties; import android.net.Network; import android.net.wifi.WifiManager; import android.os.BatteryManager; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.INetworkManagementService; @@ -1007,4 +1008,14 @@ public final class Utils extends com.android.settingslib.Utils { return context.getResources(); } } + + /** + * Returns true if SYSTEM_ALERT_WINDOW permission is available. + * Starting from Q, SYSTEM_ALERT_WINDOW is disabled on low ram phones. + */ + public static boolean isSystemAlertWindowEnabled(Context context) { + // SYSTEM_ALERT_WINDOW is disabled on on low ram devices starting from Q + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + return !(am.isLowRamDevice() && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)); + } } diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java index ee0cb7d784e..921af04fad5 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettings.java +++ b/src/com/android/settings/accessibility/AccessibilitySettings.java @@ -57,6 +57,7 @@ import com.android.internal.view.RotationPolicy.RotationPolicyListener; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; +import com.android.settings.display.DarkUIPreferenceController; import com.android.settings.display.ToggleFontSizePreferenceFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; @@ -133,6 +134,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements "accessibility_content_timeout_preference_fragment"; private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE = "accessibility_control_timeout_preference_fragment"; + private static final String DARK_UI_MODE_PREFERENCE = + "dark_ui_mode_accessibility"; // Extras passed to sub-fragments. @@ -236,6 +239,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements private SwitchPreference mToggleInversionPreference; private ColorInversionPreferenceController mInversionPreferenceController; private AccessibilityHearingAidPreferenceController mHearingAidPreferenceController; + private ListPreference mDarkUIModePreference; + private DarkUIPreferenceController mDarkUIPreferenceController; private int mLongPressTimeoutDefault; @@ -501,6 +506,13 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements // Vibrations. mVibrationPreferenceScreen = findPreference(VIBRATION_PREFERENCE_SCREEN); + + // Dark Mode. + mDarkUIModePreference = findPreference(DARK_UI_MODE_PREFERENCE); + mDarkUIPreferenceController = new DarkUIPreferenceController(getContext(), + DARK_UI_MODE_PREFERENCE); + mDarkUIPreferenceController.displayPreference(getPreferenceScreen()); + mDarkUIModePreference.setSummary(mDarkUIPreferenceController.getSummary()); } private void updateAllPreferences() { @@ -683,6 +695,9 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements // If the quick setting is enabled, the preference MUST be enabled. mInversionPreferenceController.updateState(mToggleInversionPreference); + // Dark Mode + mDarkUIPreferenceController.updateState(mDarkUIModePreference); + // Power button ends calls. if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER) && Utils.isVoiceCapable(getActivity())) { diff --git a/src/com/android/settings/applications/AllAppsInfoPreferenceController.java b/src/com/android/settings/applications/AllAppsInfoPreferenceController.java new file mode 100644 index 00000000000..d39c6e90b8c --- /dev/null +++ b/src/com/android/settings/applications/AllAppsInfoPreferenceController.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 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.app.usage.UsageStats; +import android.content.Context; + +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +import java.util.List; + +public class AllAppsInfoPreferenceController extends BasePreferenceController { + + private List mRecentApps; + + public AllAppsInfoPreferenceController(Context context, String key) { + super(context, key); + } + + public void setRecentApps(List recentApps) { + mRecentApps = recentApps; + } + + @Override + public int getAvailabilityStatus() { + return mRecentApps == null || mRecentApps.isEmpty() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + // Show total number of installed apps as See all's summary. + new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON, + mContext.getPackageManager()) { + @Override + protected void onCountComplete(int num) { + preference.setSummary(mContext.getString(R.string.apps_summary, num)); + } + }.execute(); + } +} diff --git a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java index 48483517f91..7aaf80de65c 100644 --- a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java +++ b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java @@ -36,6 +36,10 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment { private static final String TAG = "AppAndNotifDashboard"; + private boolean mIsFirstLaunch; + private RecentAppsPreferenceController mRecentAppsPreferenceController; + private AllAppsInfoPreferenceController mAllAppsInfoPreferenceController; + @Override public int getMetricsCategory() { return SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY; @@ -61,7 +65,26 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment { super.onAttach(context); use(SpecialAppAccessPreferenceController.class).setSession(getSettingsLifecycle()); - use(RecentAppsPreferenceController.class).setFragment(this /* fragment */); + mRecentAppsPreferenceController = use(RecentAppsPreferenceController.class); + mRecentAppsPreferenceController.setFragment(this /* fragment */); + + mAllAppsInfoPreferenceController = use(AllAppsInfoPreferenceController.class); + mAllAppsInfoPreferenceController.setRecentApps( + mRecentAppsPreferenceController.getRecentApps()); + + mIsFirstLaunch = true; + } + + @Override + public void onResume() { + if (!mIsFirstLaunch) { + mRecentAppsPreferenceController.reloadData(); + mAllAppsInfoPreferenceController.setRecentApps( + mRecentAppsPreferenceController.getRecentApps()); + } + + super.onResume(); + mIsFirstLaunch = false; } @Override diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java index 838d75849ac..c0d18c6eb81 100644 --- a/src/com/android/settings/applications/RecentAppsPreferenceController.java +++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java @@ -66,8 +66,6 @@ import java.util.Set; public class RecentAppsPreferenceController extends BasePreferenceController implements Comparator { - @VisibleForTesting - static final String KEY_ALL_APP_INFO = "all_app_info"; @VisibleForTesting static final String KEY_DIVIDER = "recent_apps_divider"; @@ -79,11 +77,7 @@ public class RecentAppsPreferenceController extends BasePreferenceController @VisibleForTesting LayoutPreference mRecentAppsPreference; @VisibleForTesting - Preference mAllAppPref; - @VisibleForTesting Preference mDivider; - @VisibleForTesting - boolean mIsFirstLaunch; private final PackageManager mPm; private final UsageStatsManager mUsageStatsManager; @@ -119,7 +113,6 @@ public class RecentAppsPreferenceController extends BasePreferenceController mPowerManager = mContext.getSystemService(PowerManager.class); mUsageStatsManager = mContext.getSystemService(UsageStatsManager.class); mRecentApps = new ArrayList<>(); - mIsFirstLaunch = true; reloadData(); } @@ -129,14 +122,13 @@ public class RecentAppsPreferenceController extends BasePreferenceController @Override public int getAvailabilityStatus() { - return mRecentApps.isEmpty() ? AVAILABLE_UNSEARCHABLE : AVAILABLE; + return mRecentApps.isEmpty() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mAllAppPref = screen.findPreference(KEY_ALL_APP_INFO); mDivider = screen.findPreference(KEY_DIVIDER); mRecentAppsPreference = (LayoutPreference) screen.findPreference(getPreferenceKey()); final View view = mRecentAppsPreference.findViewById(R.id.app_entities_header); @@ -157,26 +149,18 @@ public class RecentAppsPreferenceController extends BasePreferenceController @Override public void updateState(Preference preference) { super.updateState(preference); - // In order to improve launch time, we don't load data again at first launch. - if (!mIsFirstLaunch) { - reloadData(); - refreshUi(); - } + + refreshUi(); // Show total number of installed apps as See all's summary. new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON, mContext.getPackageManager()) { @Override protected void onCountComplete(int num) { - if (mHasRecentApps) { - mAppEntitiesController.setHeaderDetails( - mContext.getString(R.string.see_all_apps_title, num)); - mAppEntitiesController.apply(); - } else { - mAllAppPref.setSummary(mContext.getString(R.string.apps_summary, num)); - } + mAppEntitiesController.setHeaderDetails( + mContext.getString(R.string.see_all_apps_title, num)); + mAppEntitiesController.apply(); } }.execute(); - mIsFirstLaunch = false; } @Override @@ -185,14 +169,16 @@ public class RecentAppsPreferenceController extends BasePreferenceController return Long.compare(b.getLastTimeUsed(), a.getLastTimeUsed()); } + List getRecentApps() { + return mRecentApps; + } + @VisibleForTesting void refreshUi() { if (mRecentApps != null && !mRecentApps.isEmpty()) { - mHasRecentApps = true; displayRecentApps(); } else { - mHasRecentApps = false; - displayOnlyAppInfo(); + mDivider.setVisible(false); } } @@ -209,13 +195,6 @@ public class RecentAppsPreferenceController extends BasePreferenceController updateDisplayableRecentAppList(); } - private void displayOnlyAppInfo() { - mDivider.setVisible(false); - mAllAppPref.setTitle(R.string.applications_settings); - mAllAppPref.setVisible(true); - mRecentAppsPreference.setVisible(false); - } - private void displayRecentApps() { int showAppsCount = 0; @@ -230,8 +209,6 @@ public class RecentAppsPreferenceController extends BasePreferenceController } } mAppEntitiesController.apply(); - mRecentAppsPreference.setVisible(true); - mAllAppPref.setVisible(false); mDivider.setVisible(true); } diff --git a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java index 9cf57bd1f65..d0b26a53328 100644 --- a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java +++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java @@ -17,6 +17,7 @@ package com.android.settings.applications.appinfo; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.settings.SettingsEnums; import android.content.Context; @@ -25,6 +26,9 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.provider.Settings; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; @@ -36,6 +40,7 @@ import androidx.preference.Preference.OnPreferenceClickListener; import androidx.preference.SwitchPreference; import com.android.settings.R; +import com.android.settings.Utils; import com.android.settings.applications.AppInfoWithHeader; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateOverlayBridge; @@ -70,6 +75,11 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc mOverlayBridge = new AppStateOverlayBridge(context, mState, null); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + if (!Utils.isSystemAlertWindowEnabled(context)) { + mPackageInfo = null; + return; + } + // find preferences addPreferencesFromResource(R.xml.draw_overlay_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); @@ -81,6 +91,18 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); } + // Override here so we don't have an empty screen + @Override + public View onCreateView (LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + // if we don't have a package info, show a page saying this is unsupported + if (mPackageInfo == null) { + return inflater.inflate(R.layout.manage_applications_apps_unsupported, null); + } + return super.onCreateView(inflater, container, savedInstanceState); + } + @Override public void onResume() { super.onResume(); @@ -142,6 +164,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc @Override protected boolean refreshUi() { + if (mPackageInfo == null) return true; + mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName, mPackageInfo.applicationInfo.uid); diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index a9de206a0da..9586be01be1 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -33,6 +33,7 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; +import android.app.ActivityManager; import android.app.settings.SettingsEnums; import android.app.usage.IUsageStatsManager; import android.content.Context; @@ -49,18 +50,22 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.IconDrawableFactory; import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Filter; import android.widget.FrameLayout; import android.widget.SearchView; import android.widget.Spinner; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -79,6 +84,7 @@ import com.android.settings.Settings.StorageUseActivity; import com.android.settings.Settings.UsageAccessSettingsActivity; import com.android.settings.Settings.WriteSettingsActivity; import com.android.settings.SettingsActivity; +import com.android.settings.Utils; import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateBaseBridge; @@ -327,12 +333,19 @@ public class ManageApplications extends InstrumentedFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (mListType == LIST_TYPE_OVERLAY && !Utils.isSystemAlertWindowEnabled(getContext())) { + mRootView = inflater.inflate(R.layout.manage_applications_apps_unsupported, null); + setHasOptionsMenu(false); + return mRootView; + } + mRootView = inflater.inflate(R.layout.manage_applications_apps, null); mLoadingContainer = mRootView.findViewById(R.id.loading_container); mListContainer = mRootView.findViewById(R.id.list_container); if (mListContainer != null) { // Create adapter and list view here mEmptyView = mListContainer.findViewById(android.R.id.empty); + mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter, savedInstanceState); if (savedInstanceState != null) { diff --git a/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceController.java b/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceController.java new file mode 100644 index 00000000000..5d9e8b612b8 --- /dev/null +++ b/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceController.java @@ -0,0 +1,36 @@ +/* + * 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.specialaccess; + +import static com.android.settings.Utils.isSystemAlertWindowEnabled; + +import android.app.ActivityManager; +import android.content.Context; +import android.os.Build; + +import com.android.settings.core.BasePreferenceController; + +public class SystemAlertWindowPreferenceController extends BasePreferenceController { + public SystemAlertWindowPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return isSystemAlertWindowEnabled(mContext) + ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE ; + } +} diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java index 64c98669c0d..2c4db1f486a 100644 --- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java @@ -164,8 +164,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont new BatteryMeterView.BatteryMeterDrawable(context, context.getColor(R.color.meter_background_color)); drawable.setBatteryLevel(level); - drawable.setShowPercent(false); - drawable.setBatteryColorFilter(new PorterDuffColorFilter( + drawable.setColorFilter(new PorterDuffColorFilter( com.android.settings.Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlNormal), PorterDuff.Mode.SRC_IN)); diff --git a/src/com/android/settings/datetime/timezone/model/FilteredCountryTimeZones.java b/src/com/android/settings/datetime/timezone/model/FilteredCountryTimeZones.java index 6af0911b34f..d7fcb2f95c6 100644 --- a/src/com/android/settings/datetime/timezone/model/FilteredCountryTimeZones.java +++ b/src/com/android/settings/datetime/timezone/model/FilteredCountryTimeZones.java @@ -27,9 +27,19 @@ import java.util.stream.Collectors; */ public class FilteredCountryTimeZones { - // New timezone list and the meta data of time zone, notUsedAfter, is introduced in Android P - // in 2018. Only show time zone used in or after 2018. - private static final long MIN_USE_DATE_OF_TIMEZONE = 1514764800000L; // 1/1/2018 00:00 UTC + /** + * The timestamp used to determine which time zones to show to users by using the notUsedAfter + * metadata Android holds for each time zone. + * + * notUsedAfter exists because some time zones effectively "merge" with other time zones after + * a given point in time (i.e. they have identical transitions, offsets, etc.). After that + * point we only need to show one of the functionally identical ones. + * + * Rather than using System.currentTimeMillis(), UX folks asked for consistent behavior and so + * a timestamp known to be in the recent past is used. This should be updated occasionally but + * it doesn't have to be very often. + */ + private static final long MIN_USE_DATE_OF_TIMEZONE = 1546300800000L; // 1/1/2019 00:00 UTC private final CountryTimeZones mCountryTimeZones; private final List mTimeZoneIds; diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java index a3cff3da3d4..6a9e9fc2f7c 100644 --- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java +++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java @@ -16,11 +16,11 @@ package com.android.settings.display; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.core.TogglePreferenceController; public class AmbientDisplayAlwaysOnPreferenceController extends TogglePreferenceController { diff --git a/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java b/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java index 5c19ca7f732..daaf7b15f14 100644 --- a/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java +++ b/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java @@ -17,6 +17,7 @@ import static android.provider.Settings.Secure.DOZE_ENABLED; import android.app.settings.SettingsEnums; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; @@ -24,7 +25,6 @@ import android.text.TextUtils; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java index 822f0e9a190..aa26ff45553 100644 --- a/src/com/android/settings/fuelgauge/BatteryMeterView.java +++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java @@ -29,7 +29,7 @@ import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settingslib.graph.BatteryMeterDrawableBase; +import com.android.settingslib.graph.ThemedBatteryDrawable; public class BatteryMeterView extends ImageView { @VisibleForTesting @@ -54,29 +54,27 @@ public class BatteryMeterView extends ImageView { final int frameColor = context.getColor(R.color.meter_background_color); mAccentColorFilter = new PorterDuffColorFilter( Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent), - PorterDuff.Mode.SRC_IN); + PorterDuff.Mode.SRC); mErrorColorFilter = new PorterDuffColorFilter( context.getColor(R.color.battery_icon_color_error), PorterDuff.Mode.SRC_IN); mDrawable = new BatteryMeterDrawable(context, frameColor); - mDrawable.setShowPercent(false); - mDrawable.setBatteryColorFilter(mAccentColorFilter); - mDrawable.setWarningColorFilter( - new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); + mDrawable.setColorFilter(mAccentColorFilter); setImageDrawable(mDrawable); + setLayerType(LAYER_TYPE_SOFTWARE, null); } public void setBatteryLevel(int level) { mDrawable.setBatteryLevel(level); if (level < mDrawable.getCriticalLevel()) { - mDrawable.setBatteryColorFilter(mErrorColorFilter); + mDrawable.setColorFilter(mErrorColorFilter); } else { - mDrawable.setBatteryColorFilter(mAccentColorFilter); + mDrawable.setColorFilter(mAccentColorFilter); } } public void setPowerSave(boolean powerSave) { - mDrawable.setPowerSave(powerSave); + mDrawable.setPowerSaveEnabled(powerSave); mPowerSaveEnabled = powerSave; } @@ -85,7 +83,7 @@ public class BatteryMeterView extends ImageView { } public int getBatteryLevel() { - return mDrawable.getBatteryLevel(); + return mDrawable.getLevel(); } public void setCharging(boolean charging) { @@ -97,7 +95,7 @@ public class BatteryMeterView extends ImageView { return mDrawable.getCharging(); } - public static class BatteryMeterDrawable extends BatteryMeterDrawableBase { + public static class BatteryMeterDrawable extends ThemedBatteryDrawable { private final int mIntrinsicWidth; private final int mIntrinsicHeight; @@ -119,16 +117,5 @@ public class BatteryMeterView extends ImageView { public int getIntrinsicHeight() { return mIntrinsicHeight; } - - public void setWarningColorFilter(@Nullable ColorFilter colorFilter) { - mWarningTextPaint.setColorFilter(colorFilter); - } - - public void setBatteryColorFilter(@Nullable ColorFilter colorFilter) { - mFramePaint.setColorFilter(colorFilter); - mBatteryPaint.setColorFilter(colorFilter); - mBoltPaint.setColorFilter(colorFilter); - } } - } diff --git a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java index 9f0a613424b..4abf09af120 100644 --- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java @@ -21,14 +21,13 @@ import static android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE; import android.annotation.UserIdInt; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import androidx.annotation.VisibleForTesting; -import com.android.internal.hardware.AmbientDisplayConfiguration; - public class DoubleTapScreenPreferenceController extends GesturePreferenceController { private final int ON = 1; diff --git a/src/com/android/settings/gestures/DoubleTapScreenSettings.java b/src/com/android/settings/gestures/DoubleTapScreenSettings.java index 81225042b4f..300ce487a3e 100644 --- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java +++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java @@ -19,9 +19,9 @@ package com.android.settings.gestures; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.SearchIndexableResource; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java index c41d3c63e2a..db402cc04d9 100644 --- a/src/com/android/settings/gestures/GestureSettings.java +++ b/src/com/android/settings/gestures/GestureSettings.java @@ -18,9 +18,9 @@ package com.android.settings.gestures; import android.app.settings.SettingsEnums; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.SearchIndexableResource; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java index 9366a159817..98eddffb8fa 100644 --- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java +++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java @@ -18,11 +18,11 @@ package com.android.settings.gestures; import android.content.ContentResolver; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.Settings; import androidx.annotation.NonNull; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.overlay.FeatureFactory; diff --git a/src/com/android/settings/gestures/PickupGesturePreferenceController.java b/src/com/android/settings/gestures/PickupGesturePreferenceController.java index 7619b69621a..0738a51f0ff 100644 --- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java +++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java @@ -21,12 +21,11 @@ import static android.provider.Settings.Secure.DOZE_PICK_UP_GESTURE; import android.annotation.UserIdInt; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; -import com.android.internal.hardware.AmbientDisplayConfiguration; - public class PickupGesturePreferenceController extends GesturePreferenceController { private static final int ON = 1; diff --git a/src/com/android/settings/gestures/PickupGestureSettings.java b/src/com/android/settings/gestures/PickupGestureSettings.java index 6d479027bf0..f1cc3f05ed9 100644 --- a/src/com/android/settings/gestures/PickupGestureSettings.java +++ b/src/com/android/settings/gestures/PickupGestureSettings.java @@ -19,9 +19,9 @@ package com.android.settings.gestures; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.SearchIndexableResource; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; diff --git a/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java b/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java index bbffc7cdab7..ba2b86973fe 100644 --- a/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java +++ b/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java @@ -20,12 +20,11 @@ import static android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE; import android.annotation.UserIdInt; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; -import com.android.internal.hardware.AmbientDisplayConfiguration; - public class TapScreenGesturePreferenceController extends GesturePreferenceController { private static final String PREF_KEY_VIDEO = "gesture_tap_screen_video"; diff --git a/src/com/android/settings/gestures/TapScreenGestureSettings.java b/src/com/android/settings/gestures/TapScreenGestureSettings.java index d80c03d8f78..a86e6820afd 100644 --- a/src/com/android/settings/gestures/TapScreenGestureSettings.java +++ b/src/com/android/settings/gestures/TapScreenGestureSettings.java @@ -18,9 +18,9 @@ package com.android.settings.gestures; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.SearchIndexableResource; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; diff --git a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java index 96a3580e699..e9d03d716ac 100644 --- a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java +++ b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java @@ -20,12 +20,12 @@ import static android.provider.Settings.Secure.DOZE_WAKE_SCREEN_GESTURE; import android.annotation.UserIdInt; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.aware.AwareFeatureProvider; import com.android.settings.overlay.FeatureFactory; diff --git a/src/com/android/settings/homepage/contextualcards/CardContentProvider.java b/src/com/android/settings/homepage/contextualcards/CardContentProvider.java index e7ede14d663..a9a832d6640 100644 --- a/src/com/android/settings/homepage/contextualcards/CardContentProvider.java +++ b/src/com/android/settings/homepage/contextualcards/CardContentProvider.java @@ -39,12 +39,18 @@ public class CardContentProvider extends ContentProvider { public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider"; - public static final Uri URI = new Uri.Builder() + public static final Uri REFRESH_CARD_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CardContentProvider.CARD_AUTHORITY) .appendPath(CardDatabaseHelper.CARD_TABLE) .build(); + public static final Uri DELETE_CARD_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(CardContentProvider.CARD_AUTHORITY) + .appendPath(CardDatabaseHelper.CardColumns.CARD_DISMISSED) + .build(); + private static final String TAG = "CardContentProvider"; /** URI matcher for ContentProvider queries. */ private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java index b9bab21386b..39c48c1e847 100644 --- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java +++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java @@ -208,7 +208,7 @@ public class CardDatabaseHelper extends SQLiteOpenHelper { * Mark a specific ContextualCard with dismissal flag in the database to indicate that the * card has been dismissed. * - * @param context Context + * @param context Context * @param cardName The card name of the ContextualCard which is dismissed by user. * @return The number of rows updated */ @@ -220,7 +220,7 @@ public class CardDatabaseHelper extends SQLiteOpenHelper { final String[] selectionArgs = {cardName}; final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs); database.close(); - context.getContentResolver().notifyChange(CardContentProvider.URI, null); + context.getContentResolver().notifyChange(CardContentProvider.DELETE_CARD_URI, null); return rowsUpdated; } } diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index d6ea6ca668a..ea6ac43c693 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -59,13 +59,16 @@ public class ContextualCardLoader extends AsyncLoaderCompat private final ContentObserver mObserver = new ContentObserver( new Handler(Looper.getMainLooper())) { @Override - public void onChange(boolean selfChange) { + public void onChange(boolean selfChange, Uri uri) { if (isStarted()) { + mNotifyUri = uri; forceLoad(); } } }; + @VisibleForTesting + Uri mNotifyUri; private Context mContext; ContextualCardLoader(Context context) { @@ -77,7 +80,10 @@ public class ContextualCardLoader extends AsyncLoaderCompat @Override protected void onStartLoading() { super.onStartLoading(); - mContext.getContentResolver().registerContentObserver(CardContentProvider.URI, + mNotifyUri = null; + mContext.getContentResolver().registerContentObserver(CardContentProvider.REFRESH_CARD_URI, + false /*notifyForDescendants*/, mObserver); + mContext.getContentResolver().registerContentObserver(CardContentProvider.DELETE_CARD_URI, false /*notifyForDescendants*/, mObserver); } @@ -156,10 +162,12 @@ public class ContextualCardLoader extends AsyncLoaderCompat // Two large cards return visibleCards; } finally { - //TODO(b/121196921): Should not call this if user click dismiss - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext); - contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards); + if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) { + final ContextualCardFeatureProvider contextualCardFeatureProvider = + FeatureFactory.getFactory(mContext) + .getContextualCardFeatureProvider(mContext); + contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards); + } } } diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java index 2d40efe4f63..48e9f1e7266 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java @@ -118,7 +118,8 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life sliceLiveData.observe(mLifecycleOwner, slice -> { if (slice == null) { Log.w(TAG, "Slice is null"); - mContext.getContentResolver().notifyChange(CardContentProvider.URI, null); + mContext.getContentResolver().notifyChange(CardContentProvider.REFRESH_CARD_URI, + null); return; } else { //TODO(b/120629936): Take this out once blank card issue is fixed. diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java index cf6211246f0..4a758be809a 100644 --- a/src/com/android/settings/password/ChooseLockGeneric.java +++ b/src/com/android/settings/password/ChooseLockGeneric.java @@ -76,6 +76,7 @@ import com.android.settingslib.RestrictedPreference; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreferenceMixinCompat; +import java.util.Arrays; import java.util.List; public class ChooseLockGeneric extends SettingsActivity { @@ -151,7 +152,7 @@ public class ChooseLockGeneric extends SettingsActivity { private boolean mPasswordConfirmed = false; private boolean mWaitingForConfirmation = false; private boolean mForChangeCredRequiredForBoot = false; - private String mUserPassword; + private byte[] mUserPassword; private LockPatternUtils mLockPatternUtils; private FingerprintManager mFingerprintManager; private FaceManager mFaceManager; @@ -200,7 +201,7 @@ public class ChooseLockGeneric extends SettingsActivity { .getBooleanExtra(CONFIRM_CREDENTIALS, true); if (getActivity() instanceof ChooseLockGeneric.InternalActivity) { mPasswordConfirmed = !confirmCredentials; - mUserPassword = getActivity().getIntent().getStringExtra( + mUserPassword = getActivity().getIntent().getByteArrayExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); } @@ -224,7 +225,7 @@ public class ChooseLockGeneric extends SettingsActivity { mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); if (mUserPassword == null) { - mUserPassword = savedInstanceState.getString( + mUserPassword = savedInstanceState.getByteArray( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); } } @@ -383,11 +384,11 @@ public class ChooseLockGeneric extends SettingsActivity { if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { mPasswordConfirmed = true; mUserPassword = data != null - ? data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD) + ? data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD) : null; updatePreferencesOrFinish(false /* isRecreatingActivity */); if (mForChangeCredRequiredForBoot) { - if (!TextUtils.isEmpty(mUserPassword)) { + if (!(mUserPassword == null || mUserPassword.length == 0)) { maybeEnableEncryption( mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false); } else { @@ -447,7 +448,7 @@ public class ChooseLockGeneric extends SettingsActivity { outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed); outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation); if (mUserPassword != null) { - outState.putString(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword); + outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword); } } @@ -669,7 +670,7 @@ public class ChooseLockGeneric extends SettingsActivity { setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning); } - protected Intent getLockManagedPasswordIntent(String password) { + protected Intent getLockManagedPasswordIntent(byte[] password) { return mManagedPasswordProvider.createIntent(false, password); } diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index cd481823ec0..c9d1af339d8 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -78,6 +78,7 @@ import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class ChooseLockPassword extends SettingsActivity { @@ -123,7 +124,7 @@ public class ChooseLockPassword extends SettingsActivity { return this; } - public IntentBuilder setPassword(String password) { + public IntentBuilder setPassword(byte[] password) { mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password); return this; } @@ -185,8 +186,8 @@ public class ChooseLockPassword extends SettingsActivity { private static final String KEY_CURRENT_PASSWORD = "current_password"; private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; - private String mCurrentPassword; - private String mChosenPassword; + private byte[] mCurrentPassword; + private byte[] mChosenPassword; private boolean mHasChallenge; private long mChallenge; private ImeAwareEditText mPasswordEntry; @@ -215,7 +216,7 @@ public class ChooseLockPassword extends SettingsActivity { protected boolean mForFingerprint; protected boolean mForFace; - private String mFirstPin; + private byte[] mFirstPin; private RecyclerView mPasswordRestrictionView; protected boolean mIsAlphaMode; protected FooterButton mSkipOrClearButton; @@ -234,7 +235,7 @@ public class ChooseLockPassword extends SettingsActivity { private static final int MIN_NUMBER_IN_PASSWORD = 4; private static final int MIN_NON_LETTER_IN_PASSWORD = 5; - // Error code returned from {@link #validatePassword(String)}. + // Error code returned from {@link #validatePassword(byte[])}. static final int NO_ERROR = 0; static final int CONTAIN_INVALID_CHARACTERS = 1 << 0; static final int TOO_SHORT = 1 << 1; @@ -394,12 +395,13 @@ public class ChooseLockPassword extends SettingsActivity { SaveAndFinishWorker w = new SaveAndFinishWorker(); final boolean required = getActivity().getIntent().getBooleanExtra( EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); - String current = intent.getStringExtra( + byte[] currentBytes = intent.getByteArrayExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + w.setBlocking(true); w.setListener(this); - w.start(mChooseLockSettingsHelper.utils(), required, - false, 0, current, current, mRequestedQuality, mUserId); + w.start(mChooseLockSettingsHelper.utils(), required, false, 0, + currentBytes, currentBytes, mRequestedQuality, mUserId); } mTextChangedHandler = new TextChangedHandler(); } @@ -474,7 +476,8 @@ public class ChooseLockPassword extends SettingsActivity { Intent intent = getActivity().getIntent(); final boolean confirmCredentials = intent.getBooleanExtra( ChooseLockGeneric.CONFIRM_CREDENTIALS, true); - mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + mCurrentPassword = intent.getByteArrayExtra( + ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); mHasChallenge = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); @@ -486,8 +489,9 @@ public class ChooseLockPassword extends SettingsActivity { mUserId); } } else { + // restore from previous state - mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN); + mFirstPin = savedInstanceState.getByteArray(KEY_FIRST_PIN); final String state = savedInstanceState.getString(KEY_UI_STAGE); if (state != null) { mUiStage = Stage.valueOf(state); @@ -495,7 +499,7 @@ public class ChooseLockPassword extends SettingsActivity { } if (mCurrentPassword == null) { - mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD); + mCurrentPassword = savedInstanceState.getByteArray(KEY_CURRENT_PASSWORD); } // Re-attach to the exiting worker if there is one. @@ -553,8 +557,8 @@ public class ChooseLockPassword extends SettingsActivity { public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(KEY_UI_STAGE, mUiStage.name()); - outState.putString(KEY_FIRST_PIN, mFirstPin); - outState.putString(KEY_CURRENT_PASSWORD, mCurrentPassword); + outState.putByteArray(KEY_FIRST_PIN, mFirstPin); + outState.putByteArray(KEY_CURRENT_PASSWORD, mCurrentPassword); } @Override @@ -567,7 +571,7 @@ public class ChooseLockPassword extends SettingsActivity { getActivity().setResult(RESULT_FINISHED); getActivity().finish(); } else { - mCurrentPassword = data.getStringExtra( + mCurrentPassword = data.getByteArrayExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); } break; @@ -712,22 +716,22 @@ public class ChooseLockPassword extends SettingsActivity { * @return the validation result. */ @VisibleForTesting - int validatePassword(String password) { + int validatePassword(byte[] password) { int errorCode = NO_ERROR; final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password); mergeMinComplexityAndDpmRequirements(metrics.quality); - if (password.length() < mPasswordMinLength) { + if (password == null || password.length < mPasswordMinLength) { if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) { errorCode |= TOO_SHORT; } - } else if (password.length() > mPasswordMaxLength) { + } else if (password.length > mPasswordMaxLength) { errorCode |= TOO_LONG; } else { // The length requirements are fulfilled. if (!mPasswordNumSequenceAllowed && !requiresLettersOrSymbols() - && metrics.numeric == password.length()) { + && metrics.numeric == password.length) { // Check for repeated characters or sequences (e.g. '1234', '0000', '2468') // if DevicePolicyManager or min password complexity requires a complex numeric // password. There can be two cases in the UI: 1. User chooses to enroll a @@ -757,8 +761,8 @@ public class ChooseLockPassword extends SettingsActivity { } // Allow non-control Latin-1 characters only. - for (int i = 0; i < password.length(); i++) { - char c = password.charAt(i); + for (int i = 0; i < password.length; i++) { + char c = (char) password[i]; if (c < 32 || c > 127) { errorCode |= CONTAIN_INVALID_CHARACTERS; break; @@ -809,8 +813,9 @@ public class ChooseLockPassword extends SettingsActivity { public void handleNext() { if (mSaveAndFinishWorker != null) return; - mChosenPassword = mPasswordEntry.getText().toString(); - if (TextUtils.isEmpty(mChosenPassword)) { + // TODO(b/120484642): This is a point of entry for passwords from the UI + mChosenPassword = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText()); + if (mChosenPassword == null || mChosenPassword.length == 0) { return; } if (mUiStage == Stage.Introduction) { @@ -818,9 +823,11 @@ public class ChooseLockPassword extends SettingsActivity { mFirstPin = mChosenPassword; mPasswordEntry.setText(""); updateStage(Stage.NeedToConfirm); + } else { + Arrays.fill(mChosenPassword, (byte) 0); } } else if (mUiStage == Stage.NeedToConfirm) { - if (mFirstPin.equals(mChosenPassword)) { + if (Arrays.equals(mFirstPin, mChosenPassword)) { startSaveAndFinish(); } else { CharSequence tmp = mPasswordEntry.getText(); @@ -828,6 +835,7 @@ public class ChooseLockPassword extends SettingsActivity { Selection.setSelection((Spannable) tmp, 0, tmp.length()); } updateStage(Stage.ConfirmWrong); + Arrays.fill(mChosenPassword, (byte) 0); } } } @@ -940,8 +948,8 @@ public class ChooseLockPassword extends SettingsActivity { */ protected void updateUi() { final boolean canInput = mSaveAndFinishWorker == null; - String password = mPasswordEntry.getText().toString(); - final int length = password.length(); + byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText()); + final int length = password.length; if (mUiStage == Stage.Introduction) { mPasswordRestrictionView.setVisibility(View.VISIBLE); final int errorCode = validatePassword(password); @@ -967,6 +975,7 @@ public class ChooseLockPassword extends SettingsActivity { setNextText(mUiStage.buttonText); mPasswordEntryInputDisabler.setInputEnabled(canInput); + Arrays.fill(password, (byte) 0); } protected int toVisibility(boolean visibleOrGone) { @@ -1025,6 +1034,18 @@ public class ChooseLockPassword extends SettingsActivity { public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { getActivity().setResult(RESULT_FINISHED, resultData); + if (mChosenPassword != null) { + Arrays.fill(mChosenPassword, (byte) 0); + } + if (mCurrentPassword != null) { + Arrays.fill(mCurrentPassword, (byte) 0); + } + if (mFirstPin != null) { + Arrays.fill(mFirstPin, (byte) 0); + } + + mPasswordEntry.setText(""); + if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { @@ -1061,13 +1082,13 @@ public class ChooseLockPassword extends SettingsActivity { public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase { - private String mChosenPassword; - private String mCurrentPassword; + private byte[] mChosenPassword; + private byte[] mCurrentPassword; private int mRequestedQuality; public void start(LockPatternUtils utils, boolean required, boolean hasChallenge, long challenge, - String chosenPassword, String currentPassword, int requestedQuality, int userId) { + byte[] chosenPassword, byte[] currentPassword, int requestedQuality, int userId) { prepare(utils, required, hasChallenge, challenge, userId); mChosenPassword = chosenPassword; diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java index 584cc6162e3..d5ad1abfd70 100644 --- a/src/com/android/settings/password/ChooseLockPattern.java +++ b/src/com/android/settings/password/ChooseLockPattern.java @@ -55,6 +55,7 @@ import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -114,7 +115,7 @@ public class ChooseLockPattern extends SettingsActivity { return this; } - public IntentBuilder setPattern(String pattern) { + public IntentBuilder setPattern(byte[] pattern) { mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern); return this; } @@ -187,7 +188,7 @@ public class ChooseLockPattern extends SettingsActivity { private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; - private String mCurrentPattern; + private byte[] mCurrentPattern; private boolean mHasChallenge; private long mChallenge; protected TextView mTitleText; @@ -224,7 +225,7 @@ public class ChooseLockPattern extends SettingsActivity { getActivity().setResult(RESULT_FINISHED); getActivity().finish(); } else { - mCurrentPattern = data.getStringExtra( + mCurrentPattern = data.getByteArrayExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); } @@ -457,12 +458,12 @@ public class ChooseLockPattern extends SettingsActivity { SaveAndFinishWorker w = new SaveAndFinishWorker(); final boolean required = getActivity().getIntent().getBooleanExtra( EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); - String current = intent.getStringExtra( + byte[] current = intent.getByteArrayExtra( ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); w.setBlocking(true); w.setListener(this); w.start(mChooseLockSettingsHelper.utils(), required, - false, 0, LockPatternUtils.stringToPattern(current), current, mUserId); + false, 0, LockPatternUtils.byteArrayToPattern(current), current, mUserId); } mForFingerprint = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); @@ -540,7 +541,8 @@ public class ChooseLockPattern extends SettingsActivity { final boolean confirmCredentials = getActivity().getIntent() .getBooleanExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, true); Intent intent = getActivity().getIntent(); - mCurrentPattern = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + mCurrentPattern = + intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); mHasChallenge = intent.getBooleanExtra( ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); @@ -563,13 +565,13 @@ public class ChooseLockPattern extends SettingsActivity { } } else { // restore from previous state - final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE); - if (patternString != null) { - mChosenPattern = LockPatternUtils.stringToPattern(patternString); + final byte[] pattern = savedInstanceState.getByteArray(KEY_PATTERN_CHOICE); + if (pattern != null) { + mChosenPattern = LockPatternUtils.byteArrayToPattern(pattern); } if (mCurrentPattern == null) { - mCurrentPattern = savedInstanceState.getString(KEY_CURRENT_PATTERN); + mCurrentPattern = savedInstanceState.getByteArray(KEY_CURRENT_PATTERN); } updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]); @@ -665,13 +667,12 @@ public class ChooseLockPattern extends SettingsActivity { outState.putInt(KEY_UI_STAGE, mUiStage.ordinal()); if (mChosenPattern != null) { - outState.putString(KEY_PATTERN_CHOICE, - LockPatternUtils.patternToString(mChosenPattern)); + outState.putByteArray(KEY_PATTERN_CHOICE, + LockPatternUtils.patternToByteArray(mChosenPattern)); } if (mCurrentPattern != null) { - outState.putString(KEY_CURRENT_PATTERN, - mCurrentPattern); + outState.putByteArray(KEY_CURRENT_PATTERN, mCurrentPattern); } } @@ -818,6 +819,10 @@ public class ChooseLockPattern extends SettingsActivity { public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { getActivity().setResult(RESULT_FINISHED, resultData); + if (mCurrentPattern != null) { + Arrays.fill(mCurrentPattern, (byte) 0); + } + if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { @@ -831,12 +836,12 @@ public class ChooseLockPattern extends SettingsActivity { public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase { private List mChosenPattern; - private String mCurrentPattern; + private byte[] mCurrentPattern; private boolean mLockVirgin; public void start(LockPatternUtils utils, boolean credentialRequired, boolean hasChallenge, long challenge, - List chosenPattern, String currentPattern, int userId) { + List chosenPattern, byte[] currentPattern, int userId) { prepare(utils, credentialRequired, hasChallenge, challenge, userId); mCurrentPattern = currentPattern; diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java index f8938703bd7..6c619674d5f 100644 --- a/src/com/android/settings/password/ConfirmLockPassword.java +++ b/src/com/android/settings/password/ConfirmLockPassword.java @@ -323,8 +323,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { return; } - final String pin = mPasswordEntry.getText().toString(); - if (TextUtils.isEmpty(pin)) { + // TODO(b/120484642): This is a point of entry for passwords from the UI + final byte[] pin = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText()); + if (pin == null || pin.length == 0) { return; } @@ -350,7 +351,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { return getActivity() instanceof ConfirmLockPassword.InternalActivity; } - private void startVerifyPassword(final String pin, final Intent intent) { + private void startVerifyPassword(final byte[] pin, final Intent intent) { long challenge = getActivity().getIntent().getLongExtra( ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); final int localEffectiveUserId = mEffectiveUserId; @@ -381,7 +382,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { onVerifyCallback); } - private void startCheckPassword(final String pin, final Intent intent) { + private void startCheckPassword(final byte[] pin, final Intent intent) { final int localEffectiveUserId = mEffectiveUserId; mPendingLockCheck = LockPatternChecker.checkPassword( mLockPatternUtils, diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java index 29cdfef0516..6d3d6e56cfc 100644 --- a/src/com/android/settings/password/ConfirmLockPattern.java +++ b/src/com/android/settings/password/ConfirmLockPattern.java @@ -448,7 +448,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { mLockPatternUtils, pattern, challenge, localUserId, onVerifyCallback) : LockPatternChecker.verifyTiedProfileChallenge( - mLockPatternUtils, LockPatternUtils.patternToString(pattern), + mLockPatternUtils, LockPatternUtils.patternToByteArray(pattern), true, challenge, localUserId, onVerifyCallback); } @@ -473,7 +473,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, StorageManager.CRYPT_TYPE_PATTERN); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, - LockPatternUtils.patternToString(pattern)); + LockPatternUtils.patternToByteArray(pattern)); } mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, localEffectiveUserId); diff --git a/src/com/android/settings/password/ManagedLockPasswordProvider.java b/src/com/android/settings/password/ManagedLockPasswordProvider.java index 2494af556ed..5006926feb1 100644 --- a/src/com/android/settings/password/ManagedLockPasswordProvider.java +++ b/src/com/android/settings/password/ManagedLockPasswordProvider.java @@ -59,7 +59,7 @@ public class ManagedLockPasswordProvider { * @param password Current lock password. * @return Intent that should update lock password to a managed password. */ - Intent createIntent(boolean requirePasswordToDecrypt, String password) { + Intent createIntent(boolean requirePasswordToDecrypt, byte[] password) { return null; } } diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java index 2c6368e9468..453cdbfaf86 100644 --- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java +++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.permission.PermissionControllerManager; import android.permission.RuntimePermissionUsageInfo; import android.provider.DeviceConfig; @@ -31,12 +32,15 @@ import android.util.Log; import android.view.View; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.Utils; import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnCreate; +import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.widget.BarChartInfo; import com.android.settingslib.widget.BarChartPreference; @@ -48,14 +52,17 @@ import java.util.List; public class PermissionBarChartPreferenceController extends BasePreferenceController implements - PermissionControllerManager.OnPermissionUsageResultCallback, LifecycleObserver, OnStart { + PermissionControllerManager.OnPermissionUsageResultCallback, LifecycleObserver, OnCreate, + OnStart, OnSaveInstanceState { private static final String TAG = "BarChartPreferenceCtl"; + private static final String KEY_PERMISSION_USAGE = "usage_infos"; + @VisibleForTesting + List mOldUsageInfos; private PackageManager mPackageManager; private PrivacyDashboardFragment mParent; private BarChartPreference mBarChartPreference; - private List mOldUsageInfos; public PermissionBarChartPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); @@ -67,6 +74,18 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro mParent = fragment; } + @Override + public void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + mOldUsageInfos = savedInstanceState.getParcelableArrayList(KEY_PERMISSION_USAGE); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putParcelableList(KEY_PERMISSION_USAGE, mOldUsageInfos); + } + @Override public int getAvailabilityStatus() { return Boolean.parseBoolean( @@ -92,6 +111,9 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro .build(); mBarChartPreference.initializeBarChart(info); + if (!mOldUsageInfos.isEmpty()) { + mBarChartPreference.setBarViewInfos(createBarViews(mOldUsageInfos)); + } } @Override @@ -100,7 +122,9 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro return; } - mBarChartPreference.updateLoadingState(true /* isLoading */); + // We don't hide chart when we have existing data. + mBarChartPreference.updateLoadingState(mOldUsageInfos.isEmpty() /* isLoading */); + // But we still need to hint user with progress bar that we are updating new usage data. mParent.setLoadingEnabled(true /* enabled */); retrievePermissionUsageData(); } diff --git a/src/com/android/settings/security/CryptKeeperSettings.java b/src/com/android/settings/security/CryptKeeperSettings.java index c80ad115ff5..6555f568947 100644 --- a/src/com/android/settings/security/CryptKeeperSettings.java +++ b/src/com/android/settings/security/CryptKeeperSettings.java @@ -173,7 +173,7 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment { if (helper.utils().getKeyguardStoredPasswordQuality(UserHandle.myUserId()) == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { - showFinalConfirmation(StorageManager.CRYPT_TYPE_DEFAULT, ""); + showFinalConfirmation(StorageManager.CRYPT_TYPE_DEFAULT, "".getBytes()); return true; } @@ -193,14 +193,14 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment { // confirmation prompt; otherwise, go back to the initial state. if (resultCode == Activity.RESULT_OK && data != null) { int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1); - String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); - if (!TextUtils.isEmpty(password)) { + byte[] password = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + if (!(password == null || password.length == 0)) { showFinalConfirmation(type, password); } } } - private void showFinalConfirmation(int type, String password) { + private void showFinalConfirmation(int type, byte[] password) { Preference preference = new Preference(getPreferenceManager().getContext()); preference.setFragment(CryptKeeperConfirm.class.getName()); preference.setTitle(R.string.crypt_keeper_confirm_title); @@ -208,16 +208,16 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment { ((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference); } - private void addEncryptionInfoToPreference(Preference preference, int type, String password) { + private void addEncryptionInfoToPreference(Preference preference, int type, byte[] password) { Activity activity = getActivity(); DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE); if (dpm.getDoNotAskCredentialsOnBoot()) { preference.getExtras().putInt(TYPE, StorageManager.CRYPT_TYPE_DEFAULT); - preference.getExtras().putString(PASSWORD, ""); + preference.getExtras().putByteArray(PASSWORD, "".getBytes()); } else { preference.getExtras().putInt(TYPE, type); - preference.getExtras().putString(PASSWORD, password); + preference.getExtras().putByteArray(PASSWORD, password); } } } diff --git a/src/com/android/settings/security/LockUnificationPreferenceController.java b/src/com/android/settings/security/LockUnificationPreferenceController.java index 978986c4c83..bf374de81cf 100644 --- a/src/com/android/settings/security/LockUnificationPreferenceController.java +++ b/src/com/android/settings/security/LockUnificationPreferenceController.java @@ -70,8 +70,8 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr private RestrictedSwitchPreference mUnifyProfile; - private String mCurrentDevicePassword; - private String mCurrentProfilePassword; + private byte[] mCurrentDevicePassword; + private byte[] mCurrentProfilePassword; private boolean mKeepDeviceLock; @Override @@ -151,13 +151,13 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST && resultCode == Activity.RESULT_OK) { mCurrentDevicePassword = - data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); launchConfirmProfileLock(); return true; } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST && resultCode == Activity.RESULT_OK) { mCurrentProfilePassword = - data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); unifyLocks(); return true; } @@ -226,7 +226,7 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr // PASSWORD_QUALITY_SOMETHING means pattern, everything above means PIN/password. if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { mLockPatternUtils.saveLockPattern( - LockPatternUtils.stringToPattern(mCurrentProfilePassword), + LockPatternUtils.byteArrayToPattern(mCurrentProfilePassword), mCurrentDevicePassword, MY_USER_ID); } else { mLockPatternUtils.saveLockPassword( diff --git a/src/com/android/settings/security/LockscreenDashboardFragment.java b/src/com/android/settings/security/LockscreenDashboardFragment.java index 1935f05ef81..3472d4802ab 100644 --- a/src/com/android/settings/security/LockscreenDashboardFragment.java +++ b/src/com/android/settings/security/LockscreenDashboardFragment.java @@ -18,11 +18,11 @@ package com.android.settings.security; import android.app.settings.SettingsEnums; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.SearchIndexableResource; import androidx.annotation.VisibleForTesting; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController; diff --git a/src/com/android/settings/users/MultiUserSwitchBarController.java b/src/com/android/settings/users/MultiUserSwitchBarController.java index 9588f714648..58de14963fa 100644 --- a/src/com/android/settings/users/MultiUserSwitchBarController.java +++ b/src/com/android/settings/users/MultiUserSwitchBarController.java @@ -17,27 +17,34 @@ package com.android.settings.users; import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.settings.widget.SwitchWidgetController; +import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; public class MultiUserSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener, LifecycleObserver, OnStart, OnStop { + private static final String TAG = "MultiUserSwitchBarCtrl"; interface OnMultiUserSwitchChangedListener { void onMultiUserSwitchChanged(boolean newState); } + @VisibleForTesting + final SwitchWidgetController mSwitchBar; - private static final String TAG = "MultiUserSwitchBarCtrl"; private final Context mContext; - private final SwitchWidgetController mSwitchBar; private final UserCapabilities mUserCapabilities; private final OnMultiUserSwitchChangedListener mListener; + MultiUserSwitchBarController(Context context, SwitchWidgetController switchBar, OnMultiUserSwitchChangedListener listener) { mContext = context; @@ -45,8 +52,15 @@ public class MultiUserSwitchBarController implements SwitchWidgetController.OnSw mListener = listener; mUserCapabilities = UserCapabilities.create(context); mSwitchBar.setChecked(mUserCapabilities.mUserSwitcherEnabled); - mSwitchBar.setEnabled(!mUserCapabilities.mDisallowSwitchUser - && !mUserCapabilities.mIsGuest && mUserCapabilities.isAdmin()); + + if (mUserCapabilities.mDisallowSwitchUser) { + mSwitchBar.setDisabledByAdmin(RestrictedLockUtilsInternal + .checkIfRestrictionEnforced(mContext, UserManager.DISALLOW_USER_SWITCH, + UserHandle.myUserId())); + } else { + mSwitchBar.setEnabled(!mUserCapabilities.mDisallowSwitchUser + && !mUserCapabilities.mIsGuest && mUserCapabilities.isAdmin()); + } mSwitchBar.setListener(this); } diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index 1d78485a94b..59d22de6742 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -376,12 +376,12 @@ public class WifiConfigController implements TextWatcher, } WifiInfo info = mAccessPoint.getInfo(); - if (info != null && info.getTxLinkSpeedMbps() != -1) { + if (info != null && info.getTxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) { addRow(group, R.string.tx_wifi_speed, String.format( res.getString(R.string.tx_link_speed), info.getTxLinkSpeedMbps())); } - if (info != null && info.getRxLinkSpeedMbps() != -1) { + if (info != null && info.getRxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) { addRow(group, R.string.rx_wifi_speed, String.format( res.getString(R.string.rx_link_speed), info.getRxLinkSpeedMbps())); } diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java index 1770a02c8f6..be5a12ffbf8 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java @@ -156,7 +156,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements cancelActivity = true; } else { final WifiNetworkConfig connectedConfig = getConnectedWifiNetworkConfigOrNull(); - if (connectedConfig == null) { + if (connectedConfig == null || !connectedConfig.isSupportWifiDpp(this)) { showChooseSavedWifiNetworkFragment(/* addToBackStack */ false); } else { mWifiNetworkConfig = connectedConfig; diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java index 2264ba6a1b9..daa41d9f8f6 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java @@ -86,7 +86,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity(); MenuItem menuItem; - if (wifiNetworkConfig.isSupportConfiguratorQrCodeScanner(getActivity())) { + if (wifiNetworkConfig.isSupportWifiDpp(getActivity())) { menuItem = menu.add(0, Menu.FIRST, 0, R.string.next_label); menuItem.setIcon(R.drawable.ic_scan_24dp); menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java index 6135cba190e..a4830734337 100644 --- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java +++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java @@ -212,7 +212,7 @@ public class WifiNetworkConfig { wifiManager.connect(wifiConfiguration, listener); } - public boolean isSupportConfiguratorQrCodeScanner(Context context) { + public boolean isSupportWifiDpp(Context context) { if (!WifiDppUtils.isWifiDppEnabled(context)) { return false; } diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index 679ab8b41ee..8d20f7f847b 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -118,10 +118,19 @@ public class WifiSlice implements CustomSliceable { final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri()); final List results = worker != null ? worker.getResults() : null; + final int apCount = results == null ? 0 : results.size(); - // Need a loading text when results are not ready. - boolean needLoadingRow = results == null; - final int apCount = needLoadingRow ? 0 : results.size(); + // Need a loading text when results are not ready or out of date. + boolean needLoadingRow = true; + int index = apCount > 0 && results.get(0).isActive() ? 1 : 0; + // This loop checks the existence of reachable APs to determine the validity of the current + // AP list. + for (; index < apCount; index++) { + if (results.get(index).isReachable()) { + needLoadingRow = false; + break; + } + } // Add AP rows final CharSequence placeholder = mContext.getText(R.string.summary_placeholder); diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java index 96d5bf5ebb7..8c53019eebb 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java @@ -21,14 +21,17 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import android.app.UiModeManager; import android.content.ContentResolver; import android.content.Context; import android.os.Vibrator; import android.provider.Settings; +import androidx.preference.ListPreference; import androidx.preference.Preference; import com.android.settings.R; +import com.android.settings.display.DarkUIPreferenceController; import com.android.settings.testutils.XmlTestUtils; import org.junit.Before; @@ -47,10 +50,13 @@ public class AccessibilitySettingsTest { "accessibility_content_timeout_preference_fragment"; private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE = "accessibility_control_timeout_preference_fragment"; + private static final String DARK_UI_MODE_PREFERENCE = + "dark_ui_mode_accessibility"; private Context mContext; private ContentResolver mContentResolver; private AccessibilitySettings mSettings; + private UiModeManager mUiModeManager; @Before public void setup() { @@ -59,6 +65,7 @@ public class AccessibilitySettingsTest { mContentResolver = mContext.getContentResolver(); mSettings = spy(new AccessibilitySettings()); doReturn(mContext).when(mSettings).getContext(); + mUiModeManager = mContext.getSystemService(UiModeManager.class); } @Test @@ -146,4 +153,29 @@ public class AccessibilitySettingsTest { assertThat(preference.getSummary()).isEqualTo(mContext.getResources().getString(resId)); } + + @Test + public void testDarkUIModePreferenceSummary_shouldUpdateSummary() { + final ListPreference darkUIModePreference = new ListPreference(mContext); + final DarkUIPreferenceController mController; + doReturn(darkUIModePreference).when(mSettings).findPreference( + DARK_UI_MODE_PREFERENCE); + mController = new DarkUIPreferenceController(mContext, DARK_UI_MODE_PREFERENCE); + final String darkUIModeDescription = modeToDescription(mUiModeManager.getNightMode()); + darkUIModePreference.setSummary(mController.getSummary()); + + assertThat(darkUIModePreference.getSummary()).isEqualTo(darkUIModeDescription); + } + + private String modeToDescription(int mode) { + String[] values = mContext.getResources().getStringArray(R.array.dark_ui_mode_entries); + switch (mode) { + case UiModeManager.MODE_NIGHT_YES: + return values[0]; + case UiModeManager.MODE_NIGHT_NO: + case UiModeManager.MODE_NIGHT_AUTO: + default: + return values[1]; + } + } } diff --git a/tests/robotests/src/com/android/settings/applications/AllAppsInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/AllAppsInfoPreferenceControllerTest.java new file mode 100644 index 00000000000..ec3cf657421 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/AllAppsInfoPreferenceControllerTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 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 static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.usage.UsageStats; +import android.content.Context; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class AllAppsInfoPreferenceControllerTest { + + private AllAppsInfoPreferenceController mController; + + @Before + public void setUp() { + final Context context = RuntimeEnvironment.application; + mController = new AllAppsInfoPreferenceController(context, "test_key"); + } + + @Test + public void getAvailabilityStatus_hasRecentApps_shouldReturnConditionallyUnavailable() { + final List stats = new ArrayList<>(); + final UsageStats stat1 = new UsageStats(); + stat1.mLastTimeUsed = System.currentTimeMillis(); + stat1.mPackageName = "pkg.class"; + stats.add(stat1); + mController.setRecentApps(stats); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_noRecentApps_shouldReturnAvailable() { + // No data + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } +} diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java index e2a16579ad4..1a28f37548f 100644 --- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java @@ -18,6 +18,7 @@ package com.android.settings.applications; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; import static com.google.common.truth.Truth.assertThat; @@ -111,7 +112,6 @@ public class RecentAppsPreferenceControllerTest { final View appEntitiesHeaderView = LayoutInflater.from(context).inflate( R.layout.app_entities_header, null /* root */); - final Preference seeAllPreference = new Preference(context); final Preference dividerPreference = new Preference(context); mRecentAppsPreference = spy(new LayoutPreference(context, appEntitiesHeaderView)); @@ -119,11 +119,8 @@ public class RecentAppsPreferenceControllerTest { mController.setFragment(mFragment); mController.mAppEntitiesController = mock(AppEntitiesHeaderController.class); mController.mRecentAppsPreference = mRecentAppsPreference; - mController.mAllAppPref = seeAllPreference; mController.mDivider = dividerPreference; - when(mScreen.findPreference(RecentAppsPreferenceController.KEY_ALL_APP_INFO)) - .thenReturn(seeAllPreference); when(mScreen.findPreference(RecentAppsPreferenceController.KEY_DIVIDER)) .thenReturn(dividerPreference); when(mScreen.findPreference("test_key")).thenReturn(mRecentAppsPreference); @@ -152,9 +149,33 @@ public class RecentAppsPreferenceControllerTest { } @Test - public void getAvailabilityStatus_noRecentApps_shouldReturnAvailableUnsearchable() { + public void getAvailabilityStatus_noRecentApps_shouldReturnConditionallyUnavailable() { // No data - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_powerSaverModeOn_shouldReturnConditionallyUnavailable() { + when(mPowerManager.isPowerSaveMode()).thenReturn(true); + + final List stats = new ArrayList<>(); + final UsageStats stat1 = new UsageStats(); + + stat1.mLastTimeUsed = System.currentTimeMillis(); + stat1.mPackageName = "pkg.class"; + stats.add(stat1); + + // stat1, stat2 are valid apps. stat3 is invalid. + when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) + .thenReturn(mAppEntry); + when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) + .thenReturn(new ResolveInfo()); + when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) + .thenReturn(stats); + mAppEntry.info = mApplicationInfo; + mController.reloadData(); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); } @Test @@ -178,25 +199,6 @@ public class RecentAppsPreferenceControllerTest { assertThat(mController.mAppEntitiesController).isNotNull(); } - @Test - public void updateState_firstLaunch_shouldNotReloadData() { - mController.mIsFirstLaunch = true; - - mController.updateState(mRecentAppsPreference); - - verify(mController, never()).reloadData(); - } - - @Test - public void updateState_afterFirstLaunch_shouldReloadDataAndRefreshUi() { - mController.mIsFirstLaunch = false; - - mController.updateState(mRecentAppsPreference); - - verify(mController).reloadData(); - verify(mController).refreshUi(); - } - @Test public void updateState_threeValidRecentOpenAppsSet_setAppEntityThreeTime() { final List stats = new ArrayList<>(); @@ -227,7 +229,7 @@ public class RecentAppsPreferenceControllerTest { when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) .thenReturn(stats); mAppEntry.info = mApplicationInfo; - mController.mIsFirstLaunch = false; + mController.reloadData(); mController.updateState(mRecentAppsPreference); @@ -235,7 +237,6 @@ public class RecentAppsPreferenceControllerTest { .setAppEntity(anyInt(), any(AppEntityInfo.class)); assertThat(mController.mRecentAppsPreference.isVisible()).isTrue(); assertThat(mController.mDivider.isVisible()).isTrue(); - assertThat(mController.mAllAppPref.isVisible()).isFalse(); } @Test @@ -268,7 +269,7 @@ public class RecentAppsPreferenceControllerTest { when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) .thenReturn(stats); mAppEntry.info = mApplicationInfo; - mController.mIsFirstLaunch = false; + mController.reloadData(); mController.updateState(mRecentAppsPreference); @@ -278,35 +279,6 @@ public class RecentAppsPreferenceControllerTest { .setAppEntity(anyInt(), any(AppEntityInfo.class)); assertThat(mController.mRecentAppsPreference.isVisible()).isTrue(); assertThat(mController.mDivider.isVisible()).isTrue(); - assertThat(mController.mAllAppPref.isVisible()).isFalse(); - } - - @Test - public void updateState_powerSaverModeOn_headerIsNotVisible() { - when(mPowerManager.isPowerSaveMode()).thenReturn(true); - - final List stats = new ArrayList<>(); - final UsageStats stat1 = new UsageStats(); - - stat1.mLastTimeUsed = System.currentTimeMillis(); - stat1.mPackageName = "pkg.class"; - stats.add(stat1); - - // stat1, stat2 are valid apps. stat3 is invalid. - when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())) - .thenReturn(mAppEntry); - when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) - .thenReturn(new ResolveInfo()); - when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) - .thenReturn(stats); - mAppEntry.info = mApplicationInfo; - mController.mIsFirstLaunch = false; - - mController.updateState(mRecentAppsPreference); - - assertThat(mController.mRecentAppsPreference.isVisible()).isFalse(); - assertThat(mController.mDivider.isVisible()).isFalse(); - assertThat(mController.mAllAppPref.isVisible()).isTrue(); } @Test @@ -341,7 +313,7 @@ public class RecentAppsPreferenceControllerTest { // Make sure stat2 is considered an instant app. ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", (InstantAppDataProvider) (ApplicationInfo info) -> info == stat2Entry.info); - mController.mIsFirstLaunch = false; + mController.reloadData(); mController.updateState(mRecentAppsPreference); @@ -417,7 +389,7 @@ public class RecentAppsPreferenceControllerTest { .thenReturn(new ResolveInfo()); when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) .thenReturn(stats); - mController.mIsFirstLaunch = false; + mController.reloadData(); mController.updateState(mRecentAppsPreference); diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceControllerTest.java new file mode 100644 index 00000000000..bc90f2bead0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/specialaccess/SystemAlertWindowPreferenceControllerTest.java @@ -0,0 +1,56 @@ +/* + * 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.specialaccess; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import com.android.settings.testutils.shadow.ShadowUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowUtils.class}) +public class SystemAlertWindowPreferenceControllerTest { + + private Context mContext; + private SystemAlertWindowPreferenceController mController; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new SystemAlertWindowPreferenceController(mContext, "key"); + } + + @Test + public void systemAlertWindow_byDefault_shouldBeShown() { + ShadowUtils.setIsSystemAlertWindowEnabled(true); + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void systemAlertWindow_lowMemory_shouldNotBeShown() { + ShadowUtils.setIsSystemAlertWindowEnabled(false); + assertThat(mController.isAvailable()).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java index f8e0a74b8c2..7cd5a232713 100644 --- a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java @@ -23,9 +23,9 @@ import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.provider.Settings; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.testutils.shadow.ShadowSecureSettings; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceControllerTest.java index e36b3947625..fbfb8a493fb 100644 --- a/tests/robotests/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceControllerTest.java @@ -29,12 +29,12 @@ import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; import android.os.UserHandle; import android.provider.Settings; import androidx.preference.SwitchPreference; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.testutils.shadow.ShadowSecureSettings; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java index 4bdcd5535b3..3e994334f9e 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java @@ -73,14 +73,14 @@ public class BatteryMeterViewTest { public void testSetBatteryInfo_levelLow_setErrorColor() { mBatteryMeterView.setBatteryLevel(BATTERY_LOW_LEVEL); - verify(mDrawable).setBatteryColorFilter(mErrorColorFilter); + verify(mDrawable).setColorFilter(mErrorColorFilter); } @Test public void testSetBatteryInfo_levelNormal_setNormalColor() { mBatteryMeterView.setBatteryLevel(BATTERY_LEVEL); - verify(mDrawable).setBatteryColorFilter(mAccentColorFilter); + verify(mDrawable).setColorFilter(mAccentColorFilter); } @Test diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java index 52cb75d8fe3..0dc7a78999a 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java @@ -26,8 +26,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/gestures/PickupGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PickupGesturePreferenceControllerTest.java index 5422eabc053..b2ba216830f 100644 --- a/tests/robotests/src/com/android/settings/gestures/PickupGesturePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/PickupGesturePreferenceControllerTest.java @@ -26,8 +26,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.SharedPreferences; +import android.hardware.display.AmbientDisplayConfiguration; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl; import org.junit.Before; diff --git a/tests/robotests/src/com/android/settings/gestures/TapScreenGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/TapScreenGesturePreferenceControllerTest.java index c09e4ebe011..12715fd8aa1 100644 --- a/tests/robotests/src/com/android/settings/gestures/TapScreenGesturePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/TapScreenGesturePreferenceControllerTest.java @@ -25,8 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.when; import android.content.Context; - -import com.android.internal.hardware.AmbientDisplayConfiguration; +import android.hardware.display.AmbientDisplayConfiguration; import org.junit.Before; import org.junit.Test; diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java index ecda5fd4386..471914af614 100644 --- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java @@ -28,8 +28,8 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import android.content.Context; +import android.hardware.display.AmbientDisplayConfiguration; -import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.aware.AwareFeatureProvider; import com.android.settings.testutils.FakeFeatureFactory; diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index 18aa1c4720b..8b04ef3fed6 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -24,7 +24,9 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; 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 android.content.Context; import android.net.Uri; @@ -33,6 +35,7 @@ import androidx.slice.Slice; import com.android.settings.R; import com.android.settings.slices.CustomSliceRegistry; +import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; import org.junit.Test; @@ -52,6 +55,7 @@ public class ContextualCardLoaderTest { private Context mContext; private ContextualCardLoader mContextualCardLoader; private EligibleCardChecker mEligibleCardChecker; + private FakeFeatureFactory mFakeFeatureFactory; @Before public void setUp() { @@ -59,6 +63,7 @@ public class ContextualCardLoaderTest { mContextualCardLoader = spy(new ContextualCardLoader(mContext)); mEligibleCardChecker = spy(new EligibleCardChecker(mContext, getContextualCard(TEST_SLICE_URI))); + mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); } @Test @@ -158,6 +163,26 @@ public class ContextualCardLoaderTest { assertThat(mContextualCardLoader.loadInBackground()).isEmpty(); } + @Test + public void getDisplayableCards_refreshCardUri_shouldLogContextualCardDisplay() { + mContextualCardLoader.mNotifyUri = CardContentProvider.REFRESH_CARD_URI; + + mContextualCardLoader.getDisplayableCards(new ArrayList()); + + verify(mFakeFeatureFactory.mContextualCardFeatureProvider).logContextualCardDisplay( + any(List.class), any(List.class)); + } + + @Test + public void getDisplayableCards_deleteCardUri_shouldNotLogContextualCardDisplay() { + mContextualCardLoader.mNotifyUri = CardContentProvider.DELETE_CARD_URI; + + mContextualCardLoader.getDisplayableCards(new ArrayList()); + + verify(mFakeFeatureFactory.mContextualCardFeatureProvider, never()) + .logContextualCardDisplay(any(List.class), any(List.class)); + } + private ContextualCard getContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName("test_card") diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java index 7e1a32c81f4..e97e01e9701 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java @@ -75,7 +75,7 @@ public class SliceContextualCardControllerTest { @Test public void onDismissed_cardShouldBeMarkedAsDismissed() { - final Uri providerUri = CardContentProvider.URI; + final Uri providerUri = CardContentProvider.REFRESH_CARD_URI; mResolver.insert(providerUri, generateOneRow()); doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class)); @@ -96,7 +96,7 @@ public class SliceContextualCardControllerTest { @Test public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() { - mResolver.insert(CardContentProvider.URI, generateOneRow()); + mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow()); final ContextualCardsFragment fragment = FragmentController.of(new ContextualCardsFragment()).create().get(); final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity()); @@ -109,7 +109,7 @@ public class SliceContextualCardControllerTest { @Test @Config(qualifiers = "mcc999") public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() { - mResolver.insert(CardContentProvider.URI, generateOneRow()); + mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow()); final ContextualCardsFragment fragment = FragmentController.of(new ContextualCardsFragment()).create().get(); final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity()); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java index 404d2057aa4..73707a63012 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java @@ -87,7 +87,7 @@ public class ChooseLockPasswordTest { @Test public void intentBuilder_setPassword_shouldAddExtras() { Intent intent = new IntentBuilder(application) - .setPassword("password") + .setPassword("password".getBytes()) .setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) .setUserId(123) .build(); @@ -95,9 +95,9 @@ public class ChooseLockPasswordTest { assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true)) .named("EXTRA_KEY_HAS_CHALLENGE") .isFalse(); - assertThat(intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) + assertThat(intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) .named("EXTRA_KEY_PASSWORD") - .isEqualTo("password"); + .isEqualTo("password".getBytes()); assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0)) .named("PASSWORD_TYPE_KEY") .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); @@ -366,7 +366,9 @@ public class ChooseLockPasswordTest { intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity); ChooseLockPassword activity = buildChooseLockPasswordActivity(intent); ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(activity); - int validateResult = fragment.validatePassword(userEnteredPassword); + byte[] userEnteredPasswordBytes = userEnteredPassword != null + ? userEnteredPassword.getBytes() : null; + int validateResult = fragment.validatePassword(userEnteredPasswordBytes); String[] messages = fragment.convertErrorCodeToMessages(validateResult); assertThat(messages).asList().containsExactly((Object[]) expectedValidationResult); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java index 6b1029c7237..3509d75ab81 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java @@ -52,7 +52,7 @@ public class ChooseLockPatternTest { @Test public void intentBuilder_setPattern_shouldAddExtras() { Intent intent = new IntentBuilder(application) - .setPattern("pattern") + .setPattern("pattern".getBytes()) .setUserId(123) .build(); @@ -61,9 +61,9 @@ public class ChooseLockPatternTest { .named("EXTRA_KEY_HAS_CHALLENGE") .isFalse(); assertThat(intent - .getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) + .getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) .named("EXTRA_KEY_PASSWORD") - .isEqualTo("pattern"); + .isEqualTo("pattern".getBytes()); assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0)) .named("EXTRA_USER_ID") .isEqualTo(123); diff --git a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java index f664f4f9140..332156e8b9a 100644 --- a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java @@ -124,6 +124,18 @@ public class PermissionBarChartPreferenceControllerTest { verify(mPreference).initializeBarChart(any(BarChartInfo.class)); } + @Test + public void displayPreference_usageInfosSet_shouldSetBarViewInfos() { + final RuntimePermissionUsageInfo info1 = + new RuntimePermissionUsageInfo("permission 1", 10); + mController.mOldUsageInfos.add(info1); + + mController.displayPreference(mScreen); + + verify(mPreference).setBarViewInfos(any(BarViewInfo[].class)); + verify(mPreference).initializeBarChart(any(BarChartInfo.class)); + } + @Test public void onPermissionUsageResult_differentPermissionResultSet_shouldSetBarViewInfos() { final List infos1 = new ArrayList<>(); @@ -159,7 +171,7 @@ public class PermissionBarChartPreferenceControllerTest { } @Test - public void onStart_permissionHubEnabled_shouldShowProgressBar() { + public void onStart_usageInfosNotSetAndPermissionHubEnabled_shouldShowProgressBar() { DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE, DeviceConfig.Privacy.PROPERTY_PERMISSIONS_HUB_ENABLED, "true", true); mController.displayPreference(mScreen); @@ -170,6 +182,21 @@ public class PermissionBarChartPreferenceControllerTest { verify(mPreference).updateLoadingState(true /* isLoading */); } + @Test + public void onStart_usageInfosSetAndPermissionHubEnabled_shouldNotUpdatePrefLoadingState() { + DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE, + DeviceConfig.Privacy.PROPERTY_PERMISSIONS_HUB_ENABLED, "true", true); + final RuntimePermissionUsageInfo info1 = + new RuntimePermissionUsageInfo("permission 1", 10); + mController.mOldUsageInfos.add(info1); + mController.displayPreference(mScreen); + + mController.onStart(); + + verify(mFragment).setLoadingEnabled(true /* enabled */); + verify(mPreference).updateLoadingState(false /* isLoading */); + } + @Test public void onStart_permissionHubDisabled_shouldNotShowProgressBar() { DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE, diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java index d84d42c3e7d..fdd447545a9 100644 --- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java +++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java @@ -253,6 +253,18 @@ public class SliceTester { assertThat(hasText(sliceItems, subtitle, null /* hints */)).isTrue(); } + /** + * Assert no slice item contains subtitle. + * + * @param sliceItems All slice items of a Slice. + * @param subtitle Subtitle for asserting. + */ + public static void assertNoSliceItemContainsSubtitle(List sliceItems, + String subtitle) { + // Subtitle has no hints + assertThat(hasText(sliceItems, subtitle, null /* hints */)).isFalse(); + } + private static boolean hasText(List sliceItems, String text, String hints) { boolean hasText = false; for (SliceItem item : sliceItems) { diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java index f2870854750..e9be346eb20 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java @@ -66,12 +66,12 @@ public class ShadowLockPatternUtils { } @Implementation - protected byte[] getPasswordHistoryHashFactor(String currentPassword, int userId) { + protected byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) { return null; } @Implementation - protected boolean checkPasswordHistory(String passwordToCheck, byte[] hashFactor, int userId) { + protected boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) { return false; } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java index 9a18c1f9aaf..bceba3c9864 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java @@ -26,6 +26,7 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.shadow.api.Shadow; +import org.robolectric.annotation.Resetter; import java.util.ArrayList; import java.util.Collections; @@ -38,6 +39,8 @@ import java.util.Set; @Implements(value = UserManager.class) public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager { + private static boolean sIsSupportsMultipleUsers; + private final List mRestrictions = new ArrayList<>(); private final Map> mRestrictionSources = new HashMap<>(); private final List mUserProfileInfos = new ArrayList<>(); @@ -50,6 +53,11 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager mUserProfileInfos.add(userInfo); } + @Resetter + public static void reset() { + sIsSupportsMultipleUsers = false; + } + @Implementation protected List getProfiles(@UserIdInt int userHandle) { return mUserProfileInfos; @@ -124,4 +132,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager public void setUserSwitcherEnabled(boolean userSwitchEnabled) { mUserSwitchEnabled = userSwitchEnabled; } + + @Implementation + protected static boolean supportsMultipleUsers() { + return sIsSupportsMultipleUsers; + } + + public void setSupportsMultipleUsers(boolean supports) { + sIsSupportsMultipleUsers = supports; + } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java index 4797e8c68fb..f8644d9e712 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java @@ -38,6 +38,7 @@ public class ShadowUtils { private static boolean sIsDemoUser; private static ComponentName sDeviceOwnerComponentName; private static Map sAppNameMap; + private static boolean sIsSystemAlertWindowEnabled; @Implementation protected static int enforceSameOwner(Context context, int userId) { @@ -113,4 +114,13 @@ public class ShadowUtils { } sAppNameMap.put(packageName, appLabel); } + + @Implementation + protected static boolean isSystemAlertWindowEnabled(Context context) { + return sIsSystemAlertWindowEnabled; + } + + public static void setIsSystemAlertWindowEnabled(boolean enabled) { + sIsSystemAlertWindowEnabled = enabled; + } } diff --git a/tests/robotests/src/com/android/settings/users/MultiUserSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/users/MultiUserSwitchBarControllerTest.java new file mode 100644 index 00000000000..718e01bebe0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/users/MultiUserSwitchBarControllerTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2019 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.users; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; + +import com.android.settings.testutils.shadow.ShadowUserManager; +import com.android.settings.widget.SwitchBar; +import com.android.settings.widget.SwitchBarController; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowUserManager.class}) +public class MultiUserSwitchBarControllerTest { + + private Context mContext; + private ShadowUserManager mUserManager; + private SwitchBarController mSwitchBarController; + + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mUserManager = ShadowUserManager.getShadow(); + mSwitchBarController = spy(new SwitchBarController(new SwitchBar(mContext))); + mUserManager.setSupportsMultipleUsers(true); + } + + @After + public void tearDown() { + ShadowUserManager.reset(); + } + + @Test + public void onStart_disallowUserSwitch_shouldSetDisabledByAdmin() { + mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()), + UserManager.DISALLOW_USER_SWITCH, true); + + final MultiUserSwitchBarController controller = new MultiUserSwitchBarController(mContext, + mSwitchBarController, null); + + verify(mSwitchBarController).setDisabledByAdmin(any()); + } + + @Test + public void onStart_allowUserSwitch_shouldNotSetDisabledByAdmin() { + mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()), + UserManager.DISALLOW_USER_SWITCH, false); + + final MultiUserSwitchBarController controller = new MultiUserSwitchBarController(mContext, + mSwitchBarController, null); + + verify(mSwitchBarController, never()).setDisabledByAdmin(any()); + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java index 308d4b57cc1..3944f84072e 100644 --- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java @@ -429,7 +429,7 @@ public class WifiDetailPreferenceControllerTest { @Test public void linkSpeedPref_shouldNotShowIfNotSet() { - when(mockWifiInfo.getTxLinkSpeedMbps()).thenReturn(-1); + when(mockWifiInfo.getTxLinkSpeedMbps()).thenReturn(WifiInfo.LINK_SPEED_UNKNOWN); displayAndResume(); @@ -447,7 +447,7 @@ public class WifiDetailPreferenceControllerTest { @Test public void rxLinkSpeedPref_shouldNotShowIfNotSet() { - when(mockWifiInfo.getRxLinkSpeedMbps()).thenReturn(-1); + when(mockWifiInfo.getRxLinkSpeedMbps()).thenReturn(WifiInfo.LINK_SPEED_UNKNOWN); displayAndResume(); diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java index 6af8f803e1e..01feb8ecaed 100644 --- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java @@ -21,6 +21,7 @@ import static android.app.slice.SliceItem.FORMAT_SLICE; import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI; import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT; +import static com.android.settings.wifi.slice.WifiSlice.WifiScanWorker; import static com.google.common.truth.Truth.assertThat; @@ -32,6 +33,8 @@ import static org.mockito.Mockito.verify; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.net.NetworkInfo; +import android.net.Uri; import android.net.wifi.WifiManager; import androidx.core.graphics.drawable.IconCompat; @@ -44,24 +47,33 @@ import androidx.slice.core.SliceQuery; import androidx.slice.widget.SliceLiveData; import com.android.settings.R; +import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.testutils.SliceTester; +import com.android.settingslib.wifi.AccessPoint; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) public class WifiSliceTest { + private static final String AP1_NAME = "ap1"; + private static final String AP2_NAME = "ap2"; + private Context mContext; private ContentResolver mResolver; private WifiManager mWifiManager; private WifiSlice mWifiSlice; - private WifiSlice.WifiScanWorker mWifiScanWorker; + private WifiScanWorker mWifiScanWorker; @Before public void setUp() { @@ -75,7 +87,7 @@ public class WifiSliceTest { mWifiManager.setWifiEnabled(true); mWifiSlice = new WifiSlice(mContext); - mWifiScanWorker = new WifiSlice.WifiScanWorker(mContext, WIFI_SLICE_URI); + mWifiScanWorker = new WifiScanWorker(mContext, WIFI_SLICE_URI); } @Test @@ -122,6 +134,107 @@ public class WifiSliceTest { mContext.getString(R.string.wifi_empty_list_wifi_on)); } + private AccessPoint createAccessPoint(String name, boolean active, boolean reachable) { + final AccessPoint accessPoint = mock(AccessPoint.class); + doReturn(name).when(accessPoint).getConfigName(); + doReturn(active).when(accessPoint).isActive(); + doReturn(reachable).when(accessPoint).isReachable(); + if (active) { + final NetworkInfo networkInfo = mock(NetworkInfo.class); + doReturn(networkInfo).when(accessPoint).getNetworkInfo(); + doReturn(NetworkInfo.State.CONNECTED).when(networkInfo).getState(); + } + return accessPoint; + } + + private void setWorkerResults(AccessPoint... accessPoints) { + final ArrayList results = new ArrayList<>(); + for (AccessPoint ap : accessPoints) { + results.add(ap); + } + final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(mWifiSlice.getUri()); + doReturn(results).when(worker).getResults(); + } + + @Test + @Config(shadows = ShadowSliceBackgroundWorker.class) + public void getWifiSlice_noReachableAp_shouldReturnLoadingRow() { + setWorkerResults( + createAccessPoint(AP1_NAME, false, false), + createAccessPoint(AP2_NAME, false, false)); + final Slice wifiSlice = mWifiSlice.getSlice(); + + final List sliceItems = wifiSlice.getItems(); + + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME); + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME); + // Has scanning text + SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, + mContext.getString(R.string.wifi_empty_list_wifi_on)); + } + + @Test + @Config(shadows = ShadowSliceBackgroundWorker.class) + public void getWifiSlice_oneActiveAp_shouldReturnLoadingRow() { + setWorkerResults(createAccessPoint(AP1_NAME, true, true)); + final Slice wifiSlice = mWifiSlice.getSlice(); + + final List sliceItems = wifiSlice.getItems(); + + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME); + // Has scanning text + SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, + mContext.getString(R.string.wifi_empty_list_wifi_on)); + } + + @Test + @Config(shadows = ShadowSliceBackgroundWorker.class) + public void getWifiSlice_oneActiveApAndOneUnreachableAp_shouldReturnLoadingRow() { + setWorkerResults( + createAccessPoint(AP1_NAME, true, true), + createAccessPoint(AP2_NAME, false, false)); + final Slice wifiSlice = mWifiSlice.getSlice(); + + final List sliceItems = wifiSlice.getItems(); + + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME); + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME); + // Has scanning text + SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, + mContext.getString(R.string.wifi_empty_list_wifi_on)); + } + + @Test + @Config(shadows = ShadowSliceBackgroundWorker.class) + public void getWifiSlice_oneReachableAp_shouldNotReturnLoadingRow() { + setWorkerResults(createAccessPoint(AP1_NAME, false, true)); + final Slice wifiSlice = mWifiSlice.getSlice(); + + final List sliceItems = wifiSlice.getItems(); + + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME); + // No scanning text + SliceTester.assertNoSliceItemContainsSubtitle(sliceItems, + mContext.getString(R.string.wifi_empty_list_wifi_on)); + } + + @Test + @Config(shadows = ShadowSliceBackgroundWorker.class) + public void getWifiSlice_allReachableAps_shouldNotReturnLoadingRow() { + setWorkerResults( + createAccessPoint(AP1_NAME, false, true), + createAccessPoint(AP2_NAME, false, true)); + final Slice wifiSlice = mWifiSlice.getSlice(); + + final List sliceItems = wifiSlice.getItems(); + + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME); + SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME); + // No scanning text + SliceTester.assertNoSliceItemContainsSubtitle(sliceItems, + mContext.getString(R.string.wifi_empty_list_wifi_on)); + } + @Test public void handleUriChange_updatesWifi() { final Intent intent = mWifiSlice.getIntent(); @@ -146,4 +259,14 @@ public class WifiSliceTest { verify(mResolver).notifyChange(WIFI_SLICE_URI, null); } + + @Implements(SliceBackgroundWorker.class) + public static class ShadowSliceBackgroundWorker { + private static WifiScanWorker mWifiScanWorker = mock(WifiScanWorker.class); + + @Implementation + public static SliceBackgroundWorker getInstance(Uri uri) { + return mWifiScanWorker; + } + } } diff --git a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java index 4c72b343d55..807ac6fa060 100644 --- a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java +++ b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java @@ -52,7 +52,9 @@ public class HomepageDisplayTests { "Display", "Sound", "Storage", - "Security & location", + "Security", + "Location", + "Privacy", "Accounts", "Accessibility", "System"