Merge "Use Device Policy dialog in switchbar"
diff --git a/res/layout/manage_applications_apps_unsupported.xml b/res/layout/manage_applications_apps_unsupported.xml
new file mode 100644
index 0000000..d7c6726
--- /dev/null
+++ b/res/layout/manage_applications_apps_unsupported.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/empty_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/disabled_feature"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+ <TextView
+ android:id="@+id/empty_body"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/disabled_feature_reason_slow_down_phone"
+ android:textAppearance="?android:attr/textAppearanceSmall"/>
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <FrameLayout
+ android:id="@+id/pinned_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ settings:layout_scrollFlags="scroll|enterAlways"/>
+ </com.google.android.material.appbar.AppBarLayout>
+
+ </LinearLayout>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 90b72e1..1058c28 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10183,6 +10183,10 @@
<!-- Note displayed when certain features are not available on low ram devices. [CHAR LIMIT=NONE] -->
<string name="disabled_low_ram_device">This feature is not available on this device</string>
+ <!-- Note displayed when certain features are not available. [CHAR LIMIT=NONE] -->
+ <string name="disabled_feature">This feature is not available</string>
+ <!-- Note displayed to explain that a feature is not available because it will slow down the phone. [CHAR LIMIT=NONE] -->
+ <string name="disabled_feature_reason_slow_down_phone">It will slow down this phone</string>
<!-- UI debug setting: preference title - enforce full raw GNSS satellite measurements [CHAR LIMIT=60] -->
<string name="enable_gnss_raw_meas_full_tracking">Force full GNSS measurements</string>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 9cb73a2..da103c5 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"/>
+ <ListPreference
+ android:key="dark_ui_mode_accessibility"
+ android:title="@string/dark_ui_mode"
+ android:dialogTitle="@string/dark_ui_mode_title"
+ android:entries="@array/dark_ui_mode_entries"
+ android:entryValues="@array/dark_ui_mode_values"
+ settings:searchable="false" />
+
<Preference
android:fragment="com.android.settings.accessibility.MagnificationPreferenceFragment"
android:key="magnification_preference_screen"
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 518379a..9dd5fea 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -27,7 +27,8 @@
android:key="all_app_info"
android:title="@string/applications_settings"
android:order="-999"
- android:fragment="com.android.settings.applications.manageapplications.ManageApplications"/>
+ android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+ settings:controller="com.android.settings.applications.AllAppsInfoPreferenceController"/>
<com.android.settingslib.widget.LayoutPreference
android:key="recent_open_apps"
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 4417d0f..05f4a81 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -42,7 +42,8 @@
android:key="system_alert_window"
android:title="@string/system_alert_window_settings"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
- settings:keywords="@string/keywords_system_alert_window">
+ settings:keywords="@string/keywords_system_alert_window"
+ settings:controller="com.android.settings.applications.specialaccess.SystemAlertWindowPreferenceController">
<extra
android:name="classname"
android:value="com.android.settings.Settings$OverlaySettingsActivity" />
diff --git a/src/com/android/settings/CryptKeeperConfirm.java b/src/com/android/settings/CryptKeeperConfirm.java
index 2484948..49d027b 100644
--- a/src/com/android/settings/CryptKeeperConfirm.java
+++ b/src/com/android/settings/CryptKeeperConfirm.java
@@ -38,6 +38,7 @@
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 @@
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 804c783..69b8c56 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -55,6 +55,7 @@
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 @@
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 ee0cb7d..921af04 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -57,6 +57,7 @@
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 @@
"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 @@
private SwitchPreference mToggleInversionPreference;
private ColorInversionPreferenceController mInversionPreferenceController;
private AccessibilityHearingAidPreferenceController mHearingAidPreferenceController;
+ private ListPreference mDarkUIModePreference;
+ private DarkUIPreferenceController mDarkUIPreferenceController;
private int mLongPressTimeoutDefault;
@@ -501,6 +506,13 @@
// 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 @@
// 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 0000000..d39c6e9
--- /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<UsageStats> mRecentApps;
+
+ public AllAppsInfoPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setRecentApps(List<UsageStats> 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 4848351..7aaf80d 100644
--- a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
+++ b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
@@ -36,6 +36,10 @@
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 @@
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 838d758..c0d18c6 100644
--- a/src/com/android/settings/applications/RecentAppsPreferenceController.java
+++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java
@@ -67,8 +67,6 @@
implements Comparator<UsageStats> {
@VisibleForTesting
- static final String KEY_ALL_APP_INFO = "all_app_info";
- @VisibleForTesting
static final String KEY_DIVIDER = "recent_apps_divider";
private static final String TAG = "RecentAppsCtrl";
@@ -79,11 +77,7 @@
@VisibleForTesting
LayoutPreference mRecentAppsPreference;
@VisibleForTesting
- Preference mAllAppPref;
- @VisibleForTesting
Preference mDivider;
- @VisibleForTesting
- boolean mIsFirstLaunch;
private final PackageManager mPm;
private final UsageStatsManager mUsageStatsManager;
@@ -119,7 +113,6 @@
mPowerManager = mContext.getSystemService(PowerManager.class);
mUsageStatsManager = mContext.getSystemService(UsageStatsManager.class);
mRecentApps = new ArrayList<>();
- mIsFirstLaunch = true;
reloadData();
}
@@ -129,14 +122,13 @@
@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 @@
@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 @@
return Long.compare(b.getLastTimeUsed(), a.getLastTimeUsed());
}
+ List<UsageStats> 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 @@
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 @@
}
}
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 9cf57bd..d0b26a5 100644
--- a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
@@ -17,6 +17,7 @@
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.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.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 @@
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 @@
.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 @@
@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 a9de206..9586be0 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -33,6 +33,7 @@
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.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.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 @@
@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 0000000..5d9e8b6
--- /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 64c9866..2c4db1f 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -164,8 +164,7 @@
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 6af0911..d7fcb2f 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 @@
*/
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<String> mTimeZoneIds;
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index a3cff3d..6a9e9fc 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 5c19ca7..daaf7b1 100644
--- a/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayNotificationsPreferenceController.java
@@ -17,6 +17,7 @@
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 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 822f0e9..aa26ff4 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -29,7 +29,7 @@
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 @@
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 int getBatteryLevel() {
- return mDrawable.getBatteryLevel();
+ return mDrawable.getLevel();
}
public void setCharging(boolean charging) {
@@ -97,7 +95,7 @@
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 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 9f0a613..4abf09a 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
@@ -21,14 +21,13 @@
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 8122504..300ce48 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
@@ -19,9 +19,9 @@
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 c41d3c6..db402cc 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -18,9 +18,9 @@
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 9366a15..98eddff 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -18,11 +18,11 @@
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 7619b69..0738a51 100644
--- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
@@ -21,12 +21,11 @@
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 6d47902..f1cc3f0 100644
--- a/src/com/android/settings/gestures/PickupGestureSettings.java
+++ b/src/com/android/settings/gestures/PickupGestureSettings.java
@@ -19,9 +19,9 @@
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 bbffc7c..ba2b869 100644
--- a/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/TapScreenGesturePreferenceController.java
@@ -20,12 +20,11 @@
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 d80c03d..a86e682 100644
--- a/src/com/android/settings/gestures/TapScreenGestureSettings.java
+++ b/src/com/android/settings/gestures/TapScreenGestureSettings.java
@@ -18,9 +18,9 @@
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 96a3580..e9d03d7 100644
--- a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
@@ -20,12 +20,12 @@
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/notification/RingtonePreferenceControllerBase.java b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
index 7b37855..733d0d9 100644
--- a/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
+++ b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
@@ -50,13 +50,18 @@
}
private void updateSummary(Preference preference) {
- Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(mContext, getRingtoneType());
- final CharSequence summary = Ringtone.getTitle(
- mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
+ final Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(
+ mContext, getRingtoneType());
+
+ final CharSequence summary;
+ if (ringtoneUri == null) {
+ summary = null;
+ } else {
+ summary = Ringtone.getTitle(
+ mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
+ }
if (summary != null) {
- ThreadUtils.postOnMainThread(() -> {
- preference.setSummary(summary);
- });
+ ThreadUtils.postOnMainThread(() -> preference.setSummary(summary));
}
}
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index cf62112..4a758be 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.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 @@
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 @@
.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 @@
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 @@
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 @@
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 @@
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 cd48182..c9d1af3 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.setupdesign.GlifLayout;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
public class ChooseLockPassword extends SettingsActivity {
@@ -123,7 +124,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 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 @@
getActivity().setResult(RESULT_FINISHED);
getActivity().finish();
} else {
- mCurrentPassword = data.getStringExtra(
+ mCurrentPassword = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
break;
@@ -712,22 +716,22 @@
* @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 @@
}
// 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 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 @@
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 @@
Selection.setSelection((Spannable) tmp, 0, tmp.length());
}
updateStage(Stage.ConfirmWrong);
+ Arrays.fill(mChosenPassword, (byte) 0);
}
}
}
@@ -940,8 +948,8 @@
*/
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 @@
setNextText(mUiStage.buttonText);
mPasswordEntryInputDisabler.setInputEnabled(canInput);
+ Arrays.fill(password, (byte) 0);
}
protected int toVisibility(boolean visibleOrGone) {
@@ -1025,6 +1034,18 @@
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 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 584cc61..d5ad1ab 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.setupdesign.GlifLayout;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -114,7 +115,7 @@
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 @@
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 @@
getActivity().setResult(RESULT_FINISHED);
getActivity().finish();
} else {
- mCurrentPattern = data.getStringExtra(
+ mCurrentPattern = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
@@ -457,12 +458,12 @@
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 @@
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 @@
}
} 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 @@
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 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 static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private List<LockPatternView.Cell> mChosenPattern;
- private String mCurrentPattern;
+ private byte[] mCurrentPattern;
private boolean mLockVirgin;
public void start(LockPatternUtils utils, boolean credentialRequired,
boolean hasChallenge, long challenge,
- List<LockPatternView.Cell> chosenPattern, String currentPattern, int userId) {
+ List<LockPatternView.Cell> 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 f893870..6c61967 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -323,8 +323,9 @@
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 @@
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 @@
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 29cdfef..6d3d6e5 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -448,7 +448,7 @@
mLockPatternUtils, pattern, challenge, localUserId,
onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge(
- mLockPatternUtils, LockPatternUtils.patternToString(pattern),
+ mLockPatternUtils, LockPatternUtils.patternToByteArray(pattern),
true, challenge, localUserId, onVerifyCallback);
}
@@ -473,7 +473,7 @@
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 2494af5..5006926 100644
--- a/src/com/android/settings/password/ManagedLockPasswordProvider.java
+++ b/src/com/android/settings/password/ManagedLockPasswordProvider.java
@@ -59,7 +59,7 @@
* @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 2c6368e..453cdbf 100644
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
@@ -24,6 +24,7 @@
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.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 @@
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<RuntimePermissionUsageInfo> mOldUsageInfos;
private PackageManager mPackageManager;
private PrivacyDashboardFragment mParent;
private BarChartPreference mBarChartPreference;
- private List<RuntimePermissionUsageInfo> mOldUsageInfos;
public PermissionBarChartPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -68,6 +75,18 @@
}
@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(
DeviceConfig.getProperty(DeviceConfig.Privacy.NAMESPACE,
@@ -92,6 +111,9 @@
.build();
mBarChartPreference.initializeBarChart(info);
+ if (!mOldUsageInfos.isEmpty()) {
+ mBarChartPreference.setBarViewInfos(createBarViews(mOldUsageInfos));
+ }
}
@Override
@@ -100,7 +122,9 @@
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 c80ad11..6555f56 100644
--- a/src/com/android/settings/security/CryptKeeperSettings.java
+++ b/src/com/android/settings/security/CryptKeeperSettings.java
@@ -173,7 +173,7 @@
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 @@
// 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 @@
((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 978986c..bf374de 100644
--- a/src/com/android/settings/security/LockUnificationPreferenceController.java
+++ b/src/com/android/settings/security/LockUnificationPreferenceController.java
@@ -70,8 +70,8 @@
private RestrictedSwitchPreference mUnifyProfile;
- private String mCurrentDevicePassword;
- private String mCurrentProfilePassword;
+ private byte[] mCurrentDevicePassword;
+ private byte[] mCurrentProfilePassword;
private boolean mKeepDeviceLock;
@Override
@@ -151,13 +151,13 @@
} 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 @@
// 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 1935f05..3472d48 100644
--- a/src/com/android/settings/security/LockscreenDashboardFragment.java
+++ b/src/com/android/settings/security/LockscreenDashboardFragment.java
@@ -18,11 +18,11 @@
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/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 1770a02..be5a12f 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -156,7 +156,7 @@
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 2264ba6..daa41d9f 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -86,7 +86,7 @@
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 6135cba..a483073 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -212,7 +212,7 @@
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 679ab8b..8d20f7f 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -118,10 +118,19 @@
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri());
final List<AccessPoint> 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 96d5bf5..8c53019 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 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 @@
"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 @@
mContentResolver = mContext.getContentResolver();
mSettings = spy(new AccessibilitySettings());
doReturn(mContext).when(mSettings).getContext();
+ mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@Test
@@ -146,4 +153,29 @@
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 0000000..ec3cf65
--- /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<UsageStats> 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 e2a1657..1a28f37 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 @@
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 @@
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 @@
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 @@
}
@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<UsageStats> 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
@@ -179,25 +200,6 @@
}
@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<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = new UsageStats();
@@ -227,7 +229,7 @@
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
- mController.mIsFirstLaunch = false;
+ mController.reloadData();
mController.updateState(mRecentAppsPreference);
@@ -235,7 +237,6 @@
.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 @@
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
- mController.mIsFirstLaunch = false;
+ mController.reloadData();
mController.updateState(mRecentAppsPreference);
@@ -278,35 +279,6 @@
.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<UsageStats> 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 @@
// 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 @@
.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 0000000..bc90f2b
--- /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 f8e0a74..7cd5a23 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 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 e36b394..fbfb8a4 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 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 4bdcd55..3e99433 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 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 52cb75d..0dc7a78 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 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 5422eab..b2ba216 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 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 c09e4eb..12715fd 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.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 ecda5fd..471914a 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.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/notification/RingtonePreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java
index f22a782..2fb1738 100644
--- a/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingtonePreferenceControllerBaseTest.java
@@ -20,31 +20,31 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.media.RingtoneManager;
+import android.provider.Settings;
import androidx.preference.Preference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class RingtonePreferenceControllerBaseTest {
- @Mock
private Context mContext;
private RingtonePreferenceControllerBase mController;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
mController = new RingtonePreferenceControllerBaseTestable(mContext);
}
@@ -56,14 +56,26 @@
@Test
public void updateState_shouldSetSummary() {
Preference preference = mock(Preference.class);
+ Settings.System.putString(mContext.getContentResolver(), Settings.System.RINGTONE,
+ "content://test/ringtone");
mController.updateState(preference);
verify(preference).setSummary(anyString());
}
+ @Test
+ public void updateState_nullRingtone_shouldNotGetTitle() {
+ Preference preference = mock(Preference.class);
+ Settings.System.putString(mContext.getContentResolver(), Settings.System.RINGTONE, null);
+
+ mController.updateState(preference);
+
+ verify(preference, never()).setSummary(anyString());
+ }
+
private class RingtonePreferenceControllerBaseTestable
- extends RingtonePreferenceControllerBase {
+ extends RingtonePreferenceControllerBase {
RingtonePreferenceControllerBaseTestable(Context context) {
super(context);
}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 404d205..73707a6 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 @@
@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 @@
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 @@
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 6b1029c..3509d75 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 @@
@Test
public void intentBuilder_setPattern_shouldAddExtras() {
Intent intent = new IntentBuilder(application)
- .setPattern("pattern")
+ .setPattern("pattern".getBytes())
.setUserId(123)
.build();
@@ -61,9 +61,9 @@
.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 f664f4f..332156e 100644
--- a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
@@ -125,6 +125,18 @@
}
@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<RuntimePermissionUsageInfo> infos1 = new ArrayList<>();
final RuntimePermissionUsageInfo info1 =
@@ -159,7 +171,7 @@
}
@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);
@@ -171,6 +183,21 @@
}
@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,
DeviceConfig.Privacy.PROPERTY_PERMISSIONS_HUB_ENABLED, "false", false);
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index d84d42c..fdd4475 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 @@
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<SliceItem> sliceItems,
+ String subtitle) {
+ // Subtitle has no hints
+ assertThat(hasText(sliceItems, subtitle, null /* hints */)).isFalse();
+ }
+
private static boolean hasText(List<SliceItem> 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 f287085..e9be346 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 @@
}
@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/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index 4797e8c..f8644d9 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 @@
private static boolean sIsDemoUser;
private static ComponentName sDeviceOwnerComponentName;
private static Map<String, String> sAppNameMap;
+ private static boolean sIsSystemAlertWindowEnabled;
@Implementation
protected static int enforceSameOwner(Context context, int userId) {
@@ -113,4 +114,13 @@
}
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/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index 6af8f80..01feb8e 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 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 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.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 @@
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 @@
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<AccessPoint> 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<SliceItem> 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<SliceItem> 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<SliceItem> 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<SliceItem> 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<SliceItem> 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 @@
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;
+ }
+ }
}