Snap for 5342135 from fd7e2b43f7 to qt-release

Change-Id: Idff875383b9d5113a33c0931671341dd124dc8ee
This commit is contained in:
android-build-team Robot
2019-02-28 04:12:45 +00:00
74 changed files with 1002 additions and 287 deletions

View File

@@ -788,7 +788,7 @@
<activity android:name=".wallpaper.WallpaperSuggestionActivity"
android:label="@string/wallpaper_settings_title"
android:icon="@drawable/ic_suggestion_wallpaper"
android:icon="@drawable/ic_wallpaper"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -1,25 +0,0 @@
<!--
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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M9,12.71l2.14,2.58l3,-3.87L18,16.57H6L9,12.71zM5,5h6V3H5C3.9,3 3,3.9 3,5v6h2V5zM19,19h-6v2h6c1.1,0 2,-0.9 2,-2v-6h-2V19zM5,19v-6H3v6c0,1.1 0.9,2 2,2h6v-2H5zM19,5v6h2V5c0,-1.1 -0.9,-2 -2,-2h-6v2H19zM16,9c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1c-0.55,0 -1,0.45 -1,1S15.45,9 16,9z"/>
</vector>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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" />

View File

@@ -38,6 +38,7 @@ import android.widget.Button;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.InstrumentedFragment;
import java.util.Arrays;
import java.util.Locale;
public class CryptKeeperConfirm extends InstrumentedFragment {
@@ -87,7 +88,12 @@ public class CryptKeeperConfirm extends InstrumentedFragment {
IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
try {
Bundle args = getIntent().getExtras();
storageManager.encryptStorage(args.getInt("type", -1), args.getString("password"));
// TODO(b/120484642): Update vold to accept a password as a byte array
byte[] passwordBytes = args.getByteArray("password");
String password = passwordBytes != null ? new String(passwordBytes) : null;
Arrays.fill(passwordBytes, (byte) 0);
storageManager.encryptStorage(args.getInt("type", -1),
password);
} catch (Exception e) {
Log.e("CryptKeeper", "Error while encrypting...", e);
}

View File

@@ -55,6 +55,7 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -1007,4 +1008,14 @@ public final class Utils extends com.android.settingslib.Utils {
return context.getResources();
}
}
/**
* Returns true if SYSTEM_ALERT_WINDOW permission is available.
* Starting from Q, SYSTEM_ALERT_WINDOW is disabled on low ram phones.
*/
public static boolean isSystemAlertWindowEnabled(Context context) {
// SYSTEM_ALERT_WINDOW is disabled on on low ram devices starting from Q
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
return !(am.isLowRamDevice() && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q));
}
}

View File

@@ -57,6 +57,7 @@ import com.android.internal.view.RotationPolicy.RotationPolicyListener;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.display.DarkUIPreferenceController;
import com.android.settings.display.ToggleFontSizePreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -133,6 +134,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
"accessibility_content_timeout_preference_fragment";
private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE =
"accessibility_control_timeout_preference_fragment";
private static final String DARK_UI_MODE_PREFERENCE =
"dark_ui_mode_accessibility";
// Extras passed to sub-fragments.
@@ -236,6 +239,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
private SwitchPreference mToggleInversionPreference;
private ColorInversionPreferenceController mInversionPreferenceController;
private AccessibilityHearingAidPreferenceController mHearingAidPreferenceController;
private ListPreference mDarkUIModePreference;
private DarkUIPreferenceController mDarkUIPreferenceController;
private int mLongPressTimeoutDefault;
@@ -501,6 +506,13 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
// Vibrations.
mVibrationPreferenceScreen = findPreference(VIBRATION_PREFERENCE_SCREEN);
// Dark Mode.
mDarkUIModePreference = findPreference(DARK_UI_MODE_PREFERENCE);
mDarkUIPreferenceController = new DarkUIPreferenceController(getContext(),
DARK_UI_MODE_PREFERENCE);
mDarkUIPreferenceController.displayPreference(getPreferenceScreen());
mDarkUIModePreference.setSummary(mDarkUIPreferenceController.getSummary());
}
private void updateAllPreferences() {
@@ -683,6 +695,9 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
// If the quick setting is enabled, the preference MUST be enabled.
mInversionPreferenceController.updateState(mToggleInversionPreference);
// Dark Mode
mDarkUIPreferenceController.updateState(mDarkUIModePreference);
// Power button ends calls.
if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
&& Utils.isVoiceCapable(getActivity())) {

View File

@@ -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();
}
}

View File

@@ -36,6 +36,10 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
private static final String TAG = "AppAndNotifDashboard";
private boolean mIsFirstLaunch;
private RecentAppsPreferenceController mRecentAppsPreferenceController;
private AllAppsInfoPreferenceController mAllAppsInfoPreferenceController;
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY;
@@ -61,7 +65,26 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
super.onAttach(context);
use(SpecialAppAccessPreferenceController.class).setSession(getSettingsLifecycle());
use(RecentAppsPreferenceController.class).setFragment(this /* fragment */);
mRecentAppsPreferenceController = use(RecentAppsPreferenceController.class);
mRecentAppsPreferenceController.setFragment(this /* fragment */);
mAllAppsInfoPreferenceController = use(AllAppsInfoPreferenceController.class);
mAllAppsInfoPreferenceController.setRecentApps(
mRecentAppsPreferenceController.getRecentApps());
mIsFirstLaunch = true;
}
@Override
public void onResume() {
if (!mIsFirstLaunch) {
mRecentAppsPreferenceController.reloadData();
mAllAppsInfoPreferenceController.setRecentApps(
mRecentAppsPreferenceController.getRecentApps());
}
super.onResume();
mIsFirstLaunch = false;
}
@Override

View File

@@ -66,8 +66,6 @@ import java.util.Set;
public class RecentAppsPreferenceController extends BasePreferenceController
implements Comparator<UsageStats> {
@VisibleForTesting
static final String KEY_ALL_APP_INFO = "all_app_info";
@VisibleForTesting
static final String KEY_DIVIDER = "recent_apps_divider";
@@ -79,11 +77,7 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@VisibleForTesting
LayoutPreference mRecentAppsPreference;
@VisibleForTesting
Preference mAllAppPref;
@VisibleForTesting
Preference mDivider;
@VisibleForTesting
boolean mIsFirstLaunch;
private final PackageManager mPm;
private final UsageStatsManager mUsageStatsManager;
@@ -119,7 +113,6 @@ public class RecentAppsPreferenceController extends BasePreferenceController
mPowerManager = mContext.getSystemService(PowerManager.class);
mUsageStatsManager = mContext.getSystemService(UsageStatsManager.class);
mRecentApps = new ArrayList<>();
mIsFirstLaunch = true;
reloadData();
}
@@ -129,14 +122,13 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@Override
public int getAvailabilityStatus() {
return mRecentApps.isEmpty() ? AVAILABLE_UNSEARCHABLE : AVAILABLE;
return mRecentApps.isEmpty() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mAllAppPref = screen.findPreference(KEY_ALL_APP_INFO);
mDivider = screen.findPreference(KEY_DIVIDER);
mRecentAppsPreference = (LayoutPreference) screen.findPreference(getPreferenceKey());
final View view = mRecentAppsPreference.findViewById(R.id.app_entities_header);
@@ -157,26 +149,18 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@Override
public void updateState(Preference preference) {
super.updateState(preference);
// In order to improve launch time, we don't load data again at first launch.
if (!mIsFirstLaunch) {
reloadData();
refreshUi();
}
refreshUi();
// Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
mContext.getPackageManager()) {
@Override
protected void onCountComplete(int num) {
if (mHasRecentApps) {
mAppEntitiesController.setHeaderDetails(
mContext.getString(R.string.see_all_apps_title, num));
mAppEntitiesController.apply();
} else {
mAllAppPref.setSummary(mContext.getString(R.string.apps_summary, num));
}
mAppEntitiesController.setHeaderDetails(
mContext.getString(R.string.see_all_apps_title, num));
mAppEntitiesController.apply();
}
}.execute();
mIsFirstLaunch = false;
}
@Override
@@ -185,14 +169,16 @@ public class RecentAppsPreferenceController extends BasePreferenceController
return Long.compare(b.getLastTimeUsed(), a.getLastTimeUsed());
}
List<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 @@ public class RecentAppsPreferenceController extends BasePreferenceController
updateDisplayableRecentAppList();
}
private void displayOnlyAppInfo() {
mDivider.setVisible(false);
mAllAppPref.setTitle(R.string.applications_settings);
mAllAppPref.setVisible(true);
mRecentAppsPreference.setVisible(false);
}
private void displayRecentApps() {
int showAppsCount = 0;
@@ -230,8 +209,6 @@ public class RecentAppsPreferenceController extends BasePreferenceController
}
}
mAppEntitiesController.apply();
mRecentAppsPreference.setVisible(true);
mAllAppPref.setVisible(false);
mDivider.setVisible(true);
}

View File

@@ -17,6 +17,7 @@ package com.android.settings.applications.appinfo;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -25,6 +26,9 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
@@ -36,6 +40,7 @@ import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateOverlayBridge;
@@ -70,6 +75,11 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
mOverlayBridge = new AppStateOverlayBridge(context, mState, null);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (!Utils.isSystemAlertWindowEnabled(context)) {
mPackageInfo = null;
return;
}
// find preferences
addPreferencesFromResource(R.xml.draw_overlay_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
@@ -81,6 +91,18 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
}
// Override here so we don't have an empty screen
@Override
public View onCreateView (LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
// if we don't have a package info, show a page saying this is unsupported
if (mPackageInfo == null) {
return inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
@@ -142,6 +164,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
@Override
protected boolean refreshUi() {
if (mPackageInfo == null) return true;
mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,
mPackageInfo.applicationInfo.uid);

View File

@@ -33,6 +33,7 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.app.usage.IUsageStatsManager;
import android.content.Context;
@@ -49,18 +50,22 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Filter;
import android.widget.FrameLayout;
import android.widget.SearchView;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -79,6 +84,7 @@ import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.Settings.UsageAccessSettingsActivity;
import com.android.settings.Settings.WriteSettingsActivity;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateBaseBridge;
@@ -327,12 +333,19 @@ public class ManageApplications extends InstrumentedFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mListType == LIST_TYPE_OVERLAY && !Utils.isSystemAlertWindowEnabled(getContext())) {
mRootView = inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
setHasOptionsMenu(false);
return mRootView;
}
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
mLoadingContainer = mRootView.findViewById(R.id.loading_container);
mListContainer = mRootView.findViewById(R.id.list_container);
if (mListContainer != null) {
// Create adapter and list view here
mEmptyView = mListContainer.findViewById(android.R.id.empty);
mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter,
savedInstanceState);
if (savedInstanceState != null) {

View File

@@ -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 ;
}
}

View File

@@ -164,8 +164,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
new BatteryMeterView.BatteryMeterDrawable(context,
context.getColor(R.color.meter_background_color));
drawable.setBatteryLevel(level);
drawable.setShowPercent(false);
drawable.setBatteryColorFilter(new PorterDuffColorFilter(
drawable.setColorFilter(new PorterDuffColorFilter(
com.android.settings.Utils.getColorAttrDefaultColor(context,
android.R.attr.colorControlNormal),
PorterDuff.Mode.SRC_IN));

View File

@@ -27,9 +27,19 @@ import java.util.stream.Collectors;
*/
public class FilteredCountryTimeZones {
// New timezone list and the meta data of time zone, notUsedAfter, is introduced in Android P
// in 2018. Only show time zone used in or after 2018.
private static final long MIN_USE_DATE_OF_TIMEZONE = 1514764800000L; // 1/1/2018 00:00 UTC
/**
* The timestamp used to determine which time zones to show to users by using the notUsedAfter
* metadata Android holds for each time zone.
*
* notUsedAfter exists because some time zones effectively "merge" with other time zones after
* a given point in time (i.e. they have identical transitions, offsets, etc.). After that
* point we only need to show one of the functionally identical ones.
*
* Rather than using System.currentTimeMillis(), UX folks asked for consistent behavior and so
* a timestamp known to be in the recent past is used. This should be updated occasionally but
* it doesn't have to be very often.
*/
private static final long MIN_USE_DATE_OF_TIMEZONE = 1546300800000L; // 1/1/2019 00:00 UTC
private final CountryTimeZones mCountryTimeZones;
private final List<String> mTimeZoneIds;

View File

@@ -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 {

View File

@@ -17,6 +17,7 @@ import static android.provider.Settings.Secure.DOZE_ENABLED;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -24,7 +25,6 @@ import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;

View File

@@ -29,7 +29,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
import com.android.settingslib.graph.ThemedBatteryDrawable;
public class BatteryMeterView extends ImageView {
@VisibleForTesting
@@ -54,29 +54,27 @@ public class BatteryMeterView extends ImageView {
final int frameColor = context.getColor(R.color.meter_background_color);
mAccentColorFilter = new PorterDuffColorFilter(
Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent),
PorterDuff.Mode.SRC_IN);
PorterDuff.Mode.SRC);
mErrorColorFilter = new PorterDuffColorFilter(
context.getColor(R.color.battery_icon_color_error), PorterDuff.Mode.SRC_IN);
mDrawable = new BatteryMeterDrawable(context, frameColor);
mDrawable.setShowPercent(false);
mDrawable.setBatteryColorFilter(mAccentColorFilter);
mDrawable.setWarningColorFilter(
new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN));
mDrawable.setColorFilter(mAccentColorFilter);
setImageDrawable(mDrawable);
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
public void setBatteryLevel(int level) {
mDrawable.setBatteryLevel(level);
if (level < mDrawable.getCriticalLevel()) {
mDrawable.setBatteryColorFilter(mErrorColorFilter);
mDrawable.setColorFilter(mErrorColorFilter);
} else {
mDrawable.setBatteryColorFilter(mAccentColorFilter);
mDrawable.setColorFilter(mAccentColorFilter);
}
}
public void setPowerSave(boolean powerSave) {
mDrawable.setPowerSave(powerSave);
mDrawable.setPowerSaveEnabled(powerSave);
mPowerSaveEnabled = powerSave;
}
@@ -85,7 +83,7 @@ public class BatteryMeterView extends ImageView {
}
public int getBatteryLevel() {
return mDrawable.getBatteryLevel();
return mDrawable.getLevel();
}
public void setCharging(boolean charging) {
@@ -97,7 +95,7 @@ public class BatteryMeterView extends ImageView {
return mDrawable.getCharging();
}
public static class BatteryMeterDrawable extends BatteryMeterDrawableBase {
public static class BatteryMeterDrawable extends ThemedBatteryDrawable {
private final int mIntrinsicWidth;
private final int mIntrinsicHeight;
@@ -119,16 +117,5 @@ public class BatteryMeterView extends ImageView {
public int getIntrinsicHeight() {
return mIntrinsicHeight;
}
public void setWarningColorFilter(@Nullable ColorFilter colorFilter) {
mWarningTextPaint.setColorFilter(colorFilter);
}
public void setBatteryColorFilter(@Nullable ColorFilter colorFilter) {
mFramePaint.setColorFilter(colorFilter);
mBatteryPaint.setColorFilter(colorFilter);
mBoltPaint.setColorFilter(colorFilter);
}
}
}

View File

@@ -21,14 +21,13 @@ import static android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import com.android.internal.hardware.AmbientDisplayConfiguration;
public class DoubleTapScreenPreferenceController extends GesturePreferenceController {
private final int ON = 1;

View File

@@ -19,9 +19,9 @@ package com.android.settings.gestures;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;

View File

@@ -18,9 +18,9 @@ package com.android.settings.gestures;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;

View File

@@ -18,11 +18,11 @@ package com.android.settings.gestures;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;

View File

@@ -21,12 +21,11 @@ import static android.provider.Settings.Secure.DOZE_PICK_UP_GESTURE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.hardware.AmbientDisplayConfiguration;
public class PickupGesturePreferenceController extends GesturePreferenceController {
private static final int ON = 1;

View File

@@ -19,9 +19,9 @@ package com.android.settings.gestures;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;

View File

@@ -20,12 +20,11 @@ import static android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.hardware.AmbientDisplayConfiguration;
public class TapScreenGesturePreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "gesture_tap_screen_video";

View File

@@ -18,9 +18,9 @@ package com.android.settings.gestures;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;

View File

@@ -20,12 +20,12 @@ import static android.provider.Settings.Secure.DOZE_WAKE_SCREEN_GESTURE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.aware.AwareFeatureProvider;
import com.android.settings.overlay.FeatureFactory;

View File

@@ -39,12 +39,18 @@ public class CardContentProvider extends ContentProvider {
public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider";
public static final Uri URI = new Uri.Builder()
public static final Uri REFRESH_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(CardContentProvider.CARD_AUTHORITY)
.appendPath(CardDatabaseHelper.CARD_TABLE)
.build();
public static final Uri DELETE_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(CardContentProvider.CARD_AUTHORITY)
.appendPath(CardDatabaseHelper.CardColumns.CARD_DISMISSED)
.build();
private static final String TAG = "CardContentProvider";
/** URI matcher for ContentProvider queries. */
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

View File

@@ -208,7 +208,7 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
* Mark a specific ContextualCard with dismissal flag in the database to indicate that the
* card has been dismissed.
*
* @param context Context
* @param context Context
* @param cardName The card name of the ContextualCard which is dismissed by user.
* @return The number of rows updated
*/
@@ -220,7 +220,7 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
final String[] selectionArgs = {cardName};
final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
database.close();
context.getContentResolver().notifyChange(CardContentProvider.URI, null);
context.getContentResolver().notifyChange(CardContentProvider.DELETE_CARD_URI, null);
return rowsUpdated;
}
}

View File

@@ -59,13 +59,16 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
private final ContentObserver mObserver = new ContentObserver(
new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
public void onChange(boolean selfChange, Uri uri) {
if (isStarted()) {
mNotifyUri = uri;
forceLoad();
}
}
};
@VisibleForTesting
Uri mNotifyUri;
private Context mContext;
ContextualCardLoader(Context context) {
@@ -77,7 +80,10 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
@Override
protected void onStartLoading() {
super.onStartLoading();
mContext.getContentResolver().registerContentObserver(CardContentProvider.URI,
mNotifyUri = null;
mContext.getContentResolver().registerContentObserver(CardContentProvider.REFRESH_CARD_URI,
false /*notifyForDescendants*/, mObserver);
mContext.getContentResolver().registerContentObserver(CardContentProvider.DELETE_CARD_URI,
false /*notifyForDescendants*/, mObserver);
}
@@ -156,10 +162,12 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
// Two large cards
return visibleCards;
} finally {
//TODO(b/121196921): Should not call this if user click dismiss
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards);
if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) {
final ContextualCardFeatureProvider contextualCardFeatureProvider =
FeatureFactory.getFactory(mContext)
.getContextualCardFeatureProvider(mContext);
contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards);
}
}
}

View File

@@ -118,7 +118,8 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
mContext.getContentResolver().notifyChange(CardContentProvider.URI, null);
mContext.getContentResolver().notifyChange(CardContentProvider.REFRESH_CARD_URI,
null);
return;
} else {
//TODO(b/120629936): Take this out once blank card issue is fixed.

View File

@@ -76,6 +76,7 @@ import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.FooterPreferenceMixinCompat;
import java.util.Arrays;
import java.util.List;
public class ChooseLockGeneric extends SettingsActivity {
@@ -151,7 +152,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private boolean mPasswordConfirmed = false;
private boolean mWaitingForConfirmation = false;
private boolean mForChangeCredRequiredForBoot = false;
private String mUserPassword;
private byte[] mUserPassword;
private LockPatternUtils mLockPatternUtils;
private FingerprintManager mFingerprintManager;
private FaceManager mFaceManager;
@@ -200,7 +201,7 @@ public class ChooseLockGeneric extends SettingsActivity {
.getBooleanExtra(CONFIRM_CREDENTIALS, true);
if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
mPasswordConfirmed = !confirmCredentials;
mUserPassword = getActivity().getIntent().getStringExtra(
mUserPassword = getActivity().getIntent().getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
@@ -224,7 +225,7 @@ public class ChooseLockGeneric extends SettingsActivity {
mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);
if (mUserPassword == null) {
mUserPassword = savedInstanceState.getString(
mUserPassword = savedInstanceState.getByteArray(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
}
@@ -383,11 +384,11 @@ public class ChooseLockGeneric extends SettingsActivity {
if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
mPasswordConfirmed = true;
mUserPassword = data != null
? data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
? data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
: null;
updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (mForChangeCredRequiredForBoot) {
if (!TextUtils.isEmpty(mUserPassword)) {
if (!(mUserPassword == null || mUserPassword.length == 0)) {
maybeEnableEncryption(
mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
} else {
@@ -447,7 +448,7 @@ public class ChooseLockGeneric extends SettingsActivity {
outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation);
if (mUserPassword != null) {
outState.putString(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword);
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword);
}
}
@@ -669,7 +670,7 @@ public class ChooseLockGeneric extends SettingsActivity {
setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
}
protected Intent getLockManagedPasswordIntent(String password) {
protected Intent getLockManagedPasswordIntent(byte[] password) {
return mManagedPasswordProvider.createIntent(false, password);
}

View File

@@ -78,6 +78,7 @@ import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ChooseLockPassword extends SettingsActivity {
@@ -123,7 +124,7 @@ public class ChooseLockPassword extends SettingsActivity {
return this;
}
public IntentBuilder setPassword(String password) {
public IntentBuilder setPassword(byte[] password) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
return this;
}
@@ -185,8 +186,8 @@ public class ChooseLockPassword extends SettingsActivity {
private static final String KEY_CURRENT_PASSWORD = "current_password";
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
private String mCurrentPassword;
private String mChosenPassword;
private byte[] mCurrentPassword;
private byte[] mChosenPassword;
private boolean mHasChallenge;
private long mChallenge;
private ImeAwareEditText mPasswordEntry;
@@ -215,7 +216,7 @@ public class ChooseLockPassword extends SettingsActivity {
protected boolean mForFingerprint;
protected boolean mForFace;
private String mFirstPin;
private byte[] mFirstPin;
private RecyclerView mPasswordRestrictionView;
protected boolean mIsAlphaMode;
protected FooterButton mSkipOrClearButton;
@@ -234,7 +235,7 @@ public class ChooseLockPassword extends SettingsActivity {
private static final int MIN_NUMBER_IN_PASSWORD = 4;
private static final int MIN_NON_LETTER_IN_PASSWORD = 5;
// Error code returned from {@link #validatePassword(String)}.
// Error code returned from {@link #validatePassword(byte[])}.
static final int NO_ERROR = 0;
static final int CONTAIN_INVALID_CHARACTERS = 1 << 0;
static final int TOO_SHORT = 1 << 1;
@@ -394,12 +395,13 @@ public class ChooseLockPassword extends SettingsActivity {
SaveAndFinishWorker w = new SaveAndFinishWorker();
final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
String current = intent.getStringExtra(
byte[] currentBytes = intent.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
w.setBlocking(true);
w.setListener(this);
w.start(mChooseLockSettingsHelper.utils(), required,
false, 0, current, current, mRequestedQuality, mUserId);
w.start(mChooseLockSettingsHelper.utils(), required, false, 0,
currentBytes, currentBytes, mRequestedQuality, mUserId);
}
mTextChangedHandler = new TextChangedHandler();
}
@@ -474,7 +476,8 @@ public class ChooseLockPassword extends SettingsActivity {
Intent intent = getActivity().getIntent();
final boolean confirmCredentials = intent.getBooleanExtra(
ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mCurrentPassword = intent.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
@@ -486,8 +489,9 @@ public class ChooseLockPassword extends SettingsActivity {
mUserId);
}
} else {
// restore from previous state
mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
mFirstPin = savedInstanceState.getByteArray(KEY_FIRST_PIN);
final String state = savedInstanceState.getString(KEY_UI_STAGE);
if (state != null) {
mUiStage = Stage.valueOf(state);
@@ -495,7 +499,7 @@ public class ChooseLockPassword extends SettingsActivity {
}
if (mCurrentPassword == null) {
mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD);
mCurrentPassword = savedInstanceState.getByteArray(KEY_CURRENT_PASSWORD);
}
// Re-attach to the exiting worker if there is one.
@@ -553,8 +557,8 @@ public class ChooseLockPassword extends SettingsActivity {
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_UI_STAGE, mUiStage.name());
outState.putString(KEY_FIRST_PIN, mFirstPin);
outState.putString(KEY_CURRENT_PASSWORD, mCurrentPassword);
outState.putByteArray(KEY_FIRST_PIN, mFirstPin);
outState.putByteArray(KEY_CURRENT_PASSWORD, mCurrentPassword);
}
@Override
@@ -567,7 +571,7 @@ public class ChooseLockPassword extends SettingsActivity {
getActivity().setResult(RESULT_FINISHED);
getActivity().finish();
} else {
mCurrentPassword = data.getStringExtra(
mCurrentPassword = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
break;
@@ -712,22 +716,22 @@ public class ChooseLockPassword extends SettingsActivity {
* @return the validation result.
*/
@VisibleForTesting
int validatePassword(String password) {
int validatePassword(byte[] password) {
int errorCode = NO_ERROR;
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
mergeMinComplexityAndDpmRequirements(metrics.quality);
if (password.length() < mPasswordMinLength) {
if (password == null || password.length < mPasswordMinLength) {
if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) {
errorCode |= TOO_SHORT;
}
} else if (password.length() > mPasswordMaxLength) {
} else if (password.length > mPasswordMaxLength) {
errorCode |= TOO_LONG;
} else {
// The length requirements are fulfilled.
if (!mPasswordNumSequenceAllowed
&& !requiresLettersOrSymbols()
&& metrics.numeric == password.length()) {
&& metrics.numeric == password.length) {
// Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
// if DevicePolicyManager or min password complexity requires a complex numeric
// password. There can be two cases in the UI: 1. User chooses to enroll a
@@ -757,8 +761,8 @@ public class ChooseLockPassword extends SettingsActivity {
}
// Allow non-control Latin-1 characters only.
for (int i = 0; i < password.length(); i++) {
char c = password.charAt(i);
for (int i = 0; i < password.length; i++) {
char c = (char) password[i];
if (c < 32 || c > 127) {
errorCode |= CONTAIN_INVALID_CHARACTERS;
break;
@@ -809,8 +813,9 @@ public class ChooseLockPassword extends SettingsActivity {
public void handleNext() {
if (mSaveAndFinishWorker != null) return;
mChosenPassword = mPasswordEntry.getText().toString();
if (TextUtils.isEmpty(mChosenPassword)) {
// TODO(b/120484642): This is a point of entry for passwords from the UI
mChosenPassword = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
if (mChosenPassword == null || mChosenPassword.length == 0) {
return;
}
if (mUiStage == Stage.Introduction) {
@@ -818,9 +823,11 @@ public class ChooseLockPassword extends SettingsActivity {
mFirstPin = mChosenPassword;
mPasswordEntry.setText("");
updateStage(Stage.NeedToConfirm);
} else {
Arrays.fill(mChosenPassword, (byte) 0);
}
} else if (mUiStage == Stage.NeedToConfirm) {
if (mFirstPin.equals(mChosenPassword)) {
if (Arrays.equals(mFirstPin, mChosenPassword)) {
startSaveAndFinish();
} else {
CharSequence tmp = mPasswordEntry.getText();
@@ -828,6 +835,7 @@ public class ChooseLockPassword extends SettingsActivity {
Selection.setSelection((Spannable) tmp, 0, tmp.length());
}
updateStage(Stage.ConfirmWrong);
Arrays.fill(mChosenPassword, (byte) 0);
}
}
}
@@ -940,8 +948,8 @@ public class ChooseLockPassword extends SettingsActivity {
*/
protected void updateUi() {
final boolean canInput = mSaveAndFinishWorker == null;
String password = mPasswordEntry.getText().toString();
final int length = password.length();
byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
final int length = password.length;
if (mUiStage == Stage.Introduction) {
mPasswordRestrictionView.setVisibility(View.VISIBLE);
final int errorCode = validatePassword(password);
@@ -967,6 +975,7 @@ public class ChooseLockPassword extends SettingsActivity {
setNextText(mUiStage.buttonText);
mPasswordEntryInputDisabler.setInputEnabled(canInput);
Arrays.fill(password, (byte) 0);
}
protected int toVisibility(boolean visibleOrGone) {
@@ -1025,6 +1034,18 @@ public class ChooseLockPassword extends SettingsActivity {
public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
getActivity().setResult(RESULT_FINISHED, resultData);
if (mChosenPassword != null) {
Arrays.fill(mChosenPassword, (byte) 0);
}
if (mCurrentPassword != null) {
Arrays.fill(mCurrentPassword, (byte) 0);
}
if (mFirstPin != null) {
Arrays.fill(mFirstPin, (byte) 0);
}
mPasswordEntry.setText("");
if (!wasSecureBefore) {
Intent intent = getRedactionInterstitialIntent(getActivity());
if (intent != null) {
@@ -1061,13 +1082,13 @@ public class ChooseLockPassword extends SettingsActivity {
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private String mChosenPassword;
private String mCurrentPassword;
private byte[] mChosenPassword;
private byte[] mCurrentPassword;
private int mRequestedQuality;
public void start(LockPatternUtils utils, boolean required,
boolean hasChallenge, long challenge,
String chosenPassword, String currentPassword, int requestedQuality, int userId) {
byte[] chosenPassword, byte[] currentPassword, int requestedQuality, int userId) {
prepare(utils, required, hasChallenge, challenge, userId);
mChosenPassword = chosenPassword;

View File

@@ -55,6 +55,7 @@ import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -114,7 +115,7 @@ public class ChooseLockPattern extends SettingsActivity {
return this;
}
public IntentBuilder setPattern(String pattern) {
public IntentBuilder setPattern(byte[] pattern) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern);
return this;
}
@@ -187,7 +188,7 @@ public class ChooseLockPattern extends SettingsActivity {
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
private String mCurrentPattern;
private byte[] mCurrentPattern;
private boolean mHasChallenge;
private long mChallenge;
protected TextView mTitleText;
@@ -224,7 +225,7 @@ public class ChooseLockPattern extends SettingsActivity {
getActivity().setResult(RESULT_FINISHED);
getActivity().finish();
} else {
mCurrentPattern = data.getStringExtra(
mCurrentPattern = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
}
@@ -457,12 +458,12 @@ public class ChooseLockPattern extends SettingsActivity {
SaveAndFinishWorker w = new SaveAndFinishWorker();
final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
String current = intent.getStringExtra(
byte[] current = intent.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
w.setBlocking(true);
w.setListener(this);
w.start(mChooseLockSettingsHelper.utils(), required,
false, 0, LockPatternUtils.stringToPattern(current), current, mUserId);
false, 0, LockPatternUtils.byteArrayToPattern(current), current, mUserId);
}
mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
@@ -540,7 +541,8 @@ public class ChooseLockPattern extends SettingsActivity {
final boolean confirmCredentials = getActivity().getIntent()
.getBooleanExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
Intent intent = getActivity().getIntent();
mCurrentPattern = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mCurrentPattern =
intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
@@ -563,13 +565,13 @@ public class ChooseLockPattern extends SettingsActivity {
}
} else {
// restore from previous state
final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
if (patternString != null) {
mChosenPattern = LockPatternUtils.stringToPattern(patternString);
final byte[] pattern = savedInstanceState.getByteArray(KEY_PATTERN_CHOICE);
if (pattern != null) {
mChosenPattern = LockPatternUtils.byteArrayToPattern(pattern);
}
if (mCurrentPattern == null) {
mCurrentPattern = savedInstanceState.getString(KEY_CURRENT_PATTERN);
mCurrentPattern = savedInstanceState.getByteArray(KEY_CURRENT_PATTERN);
}
updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
@@ -665,13 +667,12 @@ public class ChooseLockPattern extends SettingsActivity {
outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
if (mChosenPattern != null) {
outState.putString(KEY_PATTERN_CHOICE,
LockPatternUtils.patternToString(mChosenPattern));
outState.putByteArray(KEY_PATTERN_CHOICE,
LockPatternUtils.patternToByteArray(mChosenPattern));
}
if (mCurrentPattern != null) {
outState.putString(KEY_CURRENT_PATTERN,
mCurrentPattern);
outState.putByteArray(KEY_CURRENT_PATTERN, mCurrentPattern);
}
}
@@ -818,6 +819,10 @@ public class ChooseLockPattern extends SettingsActivity {
public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
getActivity().setResult(RESULT_FINISHED, resultData);
if (mCurrentPattern != null) {
Arrays.fill(mCurrentPattern, (byte) 0);
}
if (!wasSecureBefore) {
Intent intent = getRedactionInterstitialIntent(getActivity());
if (intent != null) {
@@ -831,12 +836,12 @@ public class ChooseLockPattern extends SettingsActivity {
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private List<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;

View File

@@ -323,8 +323,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return;
}
final String pin = mPasswordEntry.getText().toString();
if (TextUtils.isEmpty(pin)) {
// TODO(b/120484642): This is a point of entry for passwords from the UI
final byte[] pin = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
if (pin == null || pin.length == 0) {
return;
}
@@ -350,7 +351,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return getActivity() instanceof ConfirmLockPassword.InternalActivity;
}
private void startVerifyPassword(final String pin, final Intent intent) {
private void startVerifyPassword(final byte[] pin, final Intent intent) {
long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
final int localEffectiveUserId = mEffectiveUserId;
@@ -381,7 +382,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
onVerifyCallback);
}
private void startCheckPassword(final String pin, final Intent intent) {
private void startCheckPassword(final byte[] pin, final Intent intent) {
final int localEffectiveUserId = mEffectiveUserId;
mPendingLockCheck = LockPatternChecker.checkPassword(
mLockPatternUtils,

View File

@@ -448,7 +448,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mLockPatternUtils, pattern, challenge, localUserId,
onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge(
mLockPatternUtils, LockPatternUtils.patternToString(pattern),
mLockPatternUtils, LockPatternUtils.patternToByteArray(pattern),
true, challenge, localUserId, onVerifyCallback);
}
@@ -473,7 +473,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
LockPatternUtils.patternToString(pattern));
LockPatternUtils.patternToByteArray(pattern));
}
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
localEffectiveUserId);

View File

@@ -59,7 +59,7 @@ public class ManagedLockPasswordProvider {
* @param password Current lock password.
* @return Intent that should update lock password to a managed password.
*/
Intent createIntent(boolean requirePasswordToDecrypt, String password) {
Intent createIntent(boolean requirePasswordToDecrypt, byte[] password) {
return null;
}
}

View File

@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.permission.PermissionControllerManager;
import android.permission.RuntimePermissionUsageInfo;
import android.provider.DeviceConfig;
@@ -31,12 +32,15 @@ import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.Utils;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.widget.BarChartInfo;
import com.android.settingslib.widget.BarChartPreference;
@@ -48,14 +52,17 @@ import java.util.List;
public class PermissionBarChartPreferenceController extends BasePreferenceController implements
PermissionControllerManager.OnPermissionUsageResultCallback, LifecycleObserver, OnStart {
PermissionControllerManager.OnPermissionUsageResultCallback, LifecycleObserver, OnCreate,
OnStart, OnSaveInstanceState {
private static final String TAG = "BarChartPreferenceCtl";
private static final String KEY_PERMISSION_USAGE = "usage_infos";
@VisibleForTesting
List<RuntimePermissionUsageInfo> mOldUsageInfos;
private PackageManager mPackageManager;
private PrivacyDashboardFragment mParent;
private BarChartPreference mBarChartPreference;
private List<RuntimePermissionUsageInfo> mOldUsageInfos;
public PermissionBarChartPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -67,6 +74,18 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
mParent = fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mOldUsageInfos = savedInstanceState.getParcelableArrayList(KEY_PERMISSION_USAGE);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableList(KEY_PERMISSION_USAGE, mOldUsageInfos);
}
@Override
public int getAvailabilityStatus() {
return Boolean.parseBoolean(
@@ -92,6 +111,9 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
.build();
mBarChartPreference.initializeBarChart(info);
if (!mOldUsageInfos.isEmpty()) {
mBarChartPreference.setBarViewInfos(createBarViews(mOldUsageInfos));
}
}
@Override
@@ -100,7 +122,9 @@ public class PermissionBarChartPreferenceController extends BasePreferenceContro
return;
}
mBarChartPreference.updateLoadingState(true /* isLoading */);
// We don't hide chart when we have existing data.
mBarChartPreference.updateLoadingState(mOldUsageInfos.isEmpty() /* isLoading */);
// But we still need to hint user with progress bar that we are updating new usage data.
mParent.setLoadingEnabled(true /* enabled */);
retrievePermissionUsageData();
}

View File

@@ -173,7 +173,7 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
if (helper.utils().getKeyguardStoredPasswordQuality(UserHandle.myUserId())
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
showFinalConfirmation(StorageManager.CRYPT_TYPE_DEFAULT, "");
showFinalConfirmation(StorageManager.CRYPT_TYPE_DEFAULT, "".getBytes());
return true;
}
@@ -193,14 +193,14 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
// confirmation prompt; otherwise, go back to the initial state.
if (resultCode == Activity.RESULT_OK && data != null) {
int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1);
String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
if (!TextUtils.isEmpty(password)) {
byte[] password = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
if (!(password == null || password.length == 0)) {
showFinalConfirmation(type, password);
}
}
}
private void showFinalConfirmation(int type, String password) {
private void showFinalConfirmation(int type, byte[] password) {
Preference preference = new Preference(getPreferenceManager().getContext());
preference.setFragment(CryptKeeperConfirm.class.getName());
preference.setTitle(R.string.crypt_keeper_confirm_title);
@@ -208,16 +208,16 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference);
}
private void addEncryptionInfoToPreference(Preference preference, int type, String password) {
private void addEncryptionInfoToPreference(Preference preference, int type, byte[] password) {
Activity activity = getActivity();
DevicePolicyManager dpm = (DevicePolicyManager)
activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm.getDoNotAskCredentialsOnBoot()) {
preference.getExtras().putInt(TYPE, StorageManager.CRYPT_TYPE_DEFAULT);
preference.getExtras().putString(PASSWORD, "");
preference.getExtras().putByteArray(PASSWORD, "".getBytes());
} else {
preference.getExtras().putInt(TYPE, type);
preference.getExtras().putString(PASSWORD, password);
preference.getExtras().putByteArray(PASSWORD, password);
}
}
}

View File

@@ -70,8 +70,8 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
private RestrictedSwitchPreference mUnifyProfile;
private String mCurrentDevicePassword;
private String mCurrentProfilePassword;
private byte[] mCurrentDevicePassword;
private byte[] mCurrentProfilePassword;
private boolean mKeepDeviceLock;
@Override
@@ -151,13 +151,13 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
} else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
&& resultCode == Activity.RESULT_OK) {
mCurrentDevicePassword =
data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
launchConfirmProfileLock();
return true;
} else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
&& resultCode == Activity.RESULT_OK) {
mCurrentProfilePassword =
data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
unifyLocks();
return true;
}
@@ -226,7 +226,7 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
// PASSWORD_QUALITY_SOMETHING means pattern, everything above means PIN/password.
if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
mLockPatternUtils.saveLockPattern(
LockPatternUtils.stringToPattern(mCurrentProfilePassword),
LockPatternUtils.byteArrayToPattern(mCurrentProfilePassword),
mCurrentDevicePassword, MY_USER_ID);
} else {
mLockPatternUtils.saveLockPassword(

View File

@@ -18,11 +18,11 @@ package com.android.settings.security;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.SearchIndexableResource;
import androidx.annotation.VisibleForTesting;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController;

View File

@@ -17,27 +17,34 @@
package com.android.settings.users;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
public class MultiUserSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
LifecycleObserver, OnStart, OnStop {
private static final String TAG = "MultiUserSwitchBarCtrl";
interface OnMultiUserSwitchChangedListener {
void onMultiUserSwitchChanged(boolean newState);
}
@VisibleForTesting
final SwitchWidgetController mSwitchBar;
private static final String TAG = "MultiUserSwitchBarCtrl";
private final Context mContext;
private final SwitchWidgetController mSwitchBar;
private final UserCapabilities mUserCapabilities;
private final OnMultiUserSwitchChangedListener mListener;
MultiUserSwitchBarController(Context context, SwitchWidgetController switchBar,
OnMultiUserSwitchChangedListener listener) {
mContext = context;
@@ -45,8 +52,15 @@ public class MultiUserSwitchBarController implements SwitchWidgetController.OnSw
mListener = listener;
mUserCapabilities = UserCapabilities.create(context);
mSwitchBar.setChecked(mUserCapabilities.mUserSwitcherEnabled);
mSwitchBar.setEnabled(!mUserCapabilities.mDisallowSwitchUser
&& !mUserCapabilities.mIsGuest && mUserCapabilities.isAdmin());
if (mUserCapabilities.mDisallowSwitchUser) {
mSwitchBar.setDisabledByAdmin(RestrictedLockUtilsInternal
.checkIfRestrictionEnforced(mContext, UserManager.DISALLOW_USER_SWITCH,
UserHandle.myUserId()));
} else {
mSwitchBar.setEnabled(!mUserCapabilities.mDisallowSwitchUser
&& !mUserCapabilities.mIsGuest && mUserCapabilities.isAdmin());
}
mSwitchBar.setListener(this);
}

View File

@@ -376,12 +376,12 @@ public class WifiConfigController implements TextWatcher,
}
WifiInfo info = mAccessPoint.getInfo();
if (info != null && info.getTxLinkSpeedMbps() != -1) {
if (info != null && info.getTxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
addRow(group, R.string.tx_wifi_speed, String.format(
res.getString(R.string.tx_link_speed), info.getTxLinkSpeedMbps()));
}
if (info != null && info.getRxLinkSpeedMbps() != -1) {
if (info != null && info.getRxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
addRow(group, R.string.rx_wifi_speed, String.format(
res.getString(R.string.rx_link_speed), info.getRxLinkSpeedMbps()));
}

View File

@@ -156,7 +156,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
cancelActivity = true;
} else {
final WifiNetworkConfig connectedConfig = getConnectedWifiNetworkConfigOrNull();
if (connectedConfig == null) {
if (connectedConfig == null || !connectedConfig.isSupportWifiDpp(this)) {
showChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
} else {
mWifiNetworkConfig = connectedConfig;

View File

@@ -86,7 +86,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
MenuItem menuItem;
if (wifiNetworkConfig.isSupportConfiguratorQrCodeScanner(getActivity())) {
if (wifiNetworkConfig.isSupportWifiDpp(getActivity())) {
menuItem = menu.add(0, Menu.FIRST, 0, R.string.next_label);
menuItem.setIcon(R.drawable.ic_scan_24dp);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

View File

@@ -212,7 +212,7 @@ public class WifiNetworkConfig {
wifiManager.connect(wifiConfiguration, listener);
}
public boolean isSupportConfiguratorQrCodeScanner(Context context) {
public boolean isSupportWifiDpp(Context context) {
if (!WifiDppUtils.isWifiDppEnabled(context)) {
return false;
}

View File

@@ -118,10 +118,19 @@ public class WifiSlice implements CustomSliceable {
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);

View File

@@ -21,14 +21,17 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.app.UiModeManager;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Vibrator;
import android.provider.Settings;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.display.DarkUIPreferenceController;
import com.android.settings.testutils.XmlTestUtils;
import org.junit.Before;
@@ -47,10 +50,13 @@ public class AccessibilitySettingsTest {
"accessibility_content_timeout_preference_fragment";
private static final String ACCESSIBILITY_CONTROL_TIMEOUT_PREFERENCE =
"accessibility_control_timeout_preference_fragment";
private static final String DARK_UI_MODE_PREFERENCE =
"dark_ui_mode_accessibility";
private Context mContext;
private ContentResolver mContentResolver;
private AccessibilitySettings mSettings;
private UiModeManager mUiModeManager;
@Before
public void setup() {
@@ -59,6 +65,7 @@ public class AccessibilitySettingsTest {
mContentResolver = mContext.getContentResolver();
mSettings = spy(new AccessibilitySettings());
doReturn(mContext).when(mSettings).getContext();
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@Test
@@ -146,4 +153,29 @@ public class AccessibilitySettingsTest {
assertThat(preference.getSummary()).isEqualTo(mContext.getResources().getString(resId));
}
@Test
public void testDarkUIModePreferenceSummary_shouldUpdateSummary() {
final ListPreference darkUIModePreference = new ListPreference(mContext);
final DarkUIPreferenceController mController;
doReturn(darkUIModePreference).when(mSettings).findPreference(
DARK_UI_MODE_PREFERENCE);
mController = new DarkUIPreferenceController(mContext, DARK_UI_MODE_PREFERENCE);
final String darkUIModeDescription = modeToDescription(mUiModeManager.getNightMode());
darkUIModePreference.setSummary(mController.getSummary());
assertThat(darkUIModePreference.getSummary()).isEqualTo(darkUIModeDescription);
}
private String modeToDescription(int mode) {
String[] values = mContext.getResources().getStringArray(R.array.dark_ui_mode_entries);
switch (mode) {
case UiModeManager.MODE_NIGHT_YES:
return values[0];
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_AUTO:
default:
return values[1];
}
}
}

View File

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

View File

@@ -18,6 +18,7 @@ package com.android.settings.applications;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
@@ -111,7 +112,6 @@ public class RecentAppsPreferenceControllerTest {
final View appEntitiesHeaderView = LayoutInflater.from(context).inflate(
R.layout.app_entities_header, null /* root */);
final Preference seeAllPreference = new Preference(context);
final Preference dividerPreference = new Preference(context);
mRecentAppsPreference = spy(new LayoutPreference(context, appEntitiesHeaderView));
@@ -119,11 +119,8 @@ public class RecentAppsPreferenceControllerTest {
mController.setFragment(mFragment);
mController.mAppEntitiesController = mock(AppEntitiesHeaderController.class);
mController.mRecentAppsPreference = mRecentAppsPreference;
mController.mAllAppPref = seeAllPreference;
mController.mDivider = dividerPreference;
when(mScreen.findPreference(RecentAppsPreferenceController.KEY_ALL_APP_INFO))
.thenReturn(seeAllPreference);
when(mScreen.findPreference(RecentAppsPreferenceController.KEY_DIVIDER))
.thenReturn(dividerPreference);
when(mScreen.findPreference("test_key")).thenReturn(mRecentAppsPreference);
@@ -152,9 +149,33 @@ public class RecentAppsPreferenceControllerTest {
}
@Test
public void getAvailabilityStatus_noRecentApps_shouldReturnAvailableUnsearchable() {
public void getAvailabilityStatus_noRecentApps_shouldReturnConditionallyUnavailable() {
// No data
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_powerSaverModeOn_shouldReturnConditionallyUnavailable() {
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
final List<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
@@ -178,25 +199,6 @@ public class RecentAppsPreferenceControllerTest {
assertThat(mController.mAppEntitiesController).isNotNull();
}
@Test
public void updateState_firstLaunch_shouldNotReloadData() {
mController.mIsFirstLaunch = true;
mController.updateState(mRecentAppsPreference);
verify(mController, never()).reloadData();
}
@Test
public void updateState_afterFirstLaunch_shouldReloadDataAndRefreshUi() {
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference);
verify(mController).reloadData();
verify(mController).refreshUi();
}
@Test
public void updateState_threeValidRecentOpenAppsSet_setAppEntityThreeTime() {
final List<UsageStats> stats = new ArrayList<>();
@@ -227,7 +229,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.mIsFirstLaunch = false;
mController.reloadData();
mController.updateState(mRecentAppsPreference);
@@ -235,7 +237,6 @@ public class RecentAppsPreferenceControllerTest {
.setAppEntity(anyInt(), any(AppEntityInfo.class));
assertThat(mController.mRecentAppsPreference.isVisible()).isTrue();
assertThat(mController.mDivider.isVisible()).isTrue();
assertThat(mController.mAllAppPref.isVisible()).isFalse();
}
@Test
@@ -268,7 +269,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.mIsFirstLaunch = false;
mController.reloadData();
mController.updateState(mRecentAppsPreference);
@@ -278,35 +279,6 @@ public class RecentAppsPreferenceControllerTest {
.setAppEntity(anyInt(), any(AppEntityInfo.class));
assertThat(mController.mRecentAppsPreference.isVisible()).isTrue();
assertThat(mController.mDivider.isVisible()).isTrue();
assertThat(mController.mAllAppPref.isVisible()).isFalse();
}
@Test
public void updateState_powerSaverModeOn_headerIsNotVisible() {
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
final List<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 @@ public class RecentAppsPreferenceControllerTest {
// Make sure stat2 is considered an instant app.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (ApplicationInfo info) -> info == stat2Entry.info);
mController.mIsFirstLaunch = false;
mController.reloadData();
mController.updateState(mRecentAppsPreference);
@@ -417,7 +389,7 @@ public class RecentAppsPreferenceControllerTest {
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mController.mIsFirstLaunch = false;
mController.reloadData();
mController.updateState(mRecentAppsPreference);

View File

@@ -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();
}
}

View File

@@ -23,9 +23,9 @@ import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.Settings;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import org.junit.Before;

View File

@@ -29,12 +29,12 @@ import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;

View File

@@ -73,14 +73,14 @@ public class BatteryMeterViewTest {
public void testSetBatteryInfo_levelLow_setErrorColor() {
mBatteryMeterView.setBatteryLevel(BATTERY_LOW_LEVEL);
verify(mDrawable).setBatteryColorFilter(mErrorColorFilter);
verify(mDrawable).setColorFilter(mErrorColorFilter);
}
@Test
public void testSetBatteryInfo_levelNormal_setNormalColor() {
mBatteryMeterView.setBatteryLevel(BATTERY_LEVEL);
verify(mDrawable).setBatteryColorFilter(mAccentColorFilter);
verify(mDrawable).setColorFilter(mAccentColorFilter);
}
@Test

View File

@@ -26,8 +26,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
import org.junit.Before;

View File

@@ -26,8 +26,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.display.AmbientDisplayConfiguration;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
import org.junit.Before;

View File

@@ -25,8 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;
import android.content.Context;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import android.hardware.display.AmbientDisplayConfiguration;
import org.junit.Before;
import org.junit.Test;

View File

@@ -28,8 +28,8 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.aware.AwareFeatureProvider;
import com.android.settings.testutils.FakeFeatureFactory;

View File

@@ -24,7 +24,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.Uri;
@@ -33,6 +35,7 @@ import androidx.slice.Slice;
import com.android.settings.R;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
@@ -52,6 +55,7 @@ public class ContextualCardLoaderTest {
private Context mContext;
private ContextualCardLoader mContextualCardLoader;
private EligibleCardChecker mEligibleCardChecker;
private FakeFeatureFactory mFakeFeatureFactory;
@Before
public void setUp() {
@@ -59,6 +63,7 @@ public class ContextualCardLoaderTest {
mContextualCardLoader = spy(new ContextualCardLoader(mContext));
mEligibleCardChecker =
spy(new EligibleCardChecker(mContext, getContextualCard(TEST_SLICE_URI)));
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
}
@Test
@@ -158,6 +163,26 @@ public class ContextualCardLoaderTest {
assertThat(mContextualCardLoader.loadInBackground()).isEmpty();
}
@Test
public void getDisplayableCards_refreshCardUri_shouldLogContextualCardDisplay() {
mContextualCardLoader.mNotifyUri = CardContentProvider.REFRESH_CARD_URI;
mContextualCardLoader.getDisplayableCards(new ArrayList<ContextualCard>());
verify(mFakeFeatureFactory.mContextualCardFeatureProvider).logContextualCardDisplay(
any(List.class), any(List.class));
}
@Test
public void getDisplayableCards_deleteCardUri_shouldNotLogContextualCardDisplay() {
mContextualCardLoader.mNotifyUri = CardContentProvider.DELETE_CARD_URI;
mContextualCardLoader.getDisplayableCards(new ArrayList<ContextualCard>());
verify(mFakeFeatureFactory.mContextualCardFeatureProvider, never())
.logContextualCardDisplay(any(List.class), any(List.class));
}
private ContextualCard getContextualCard(String sliceUri) {
return new ContextualCard.Builder()
.setName("test_card")

View File

@@ -75,7 +75,7 @@ public class SliceContextualCardControllerTest {
@Test
public void onDismissed_cardShouldBeMarkedAsDismissed() {
final Uri providerUri = CardContentProvider.URI;
final Uri providerUri = CardContentProvider.REFRESH_CARD_URI;
mResolver.insert(providerUri, generateOneRow());
doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
@@ -96,7 +96,7 @@ public class SliceContextualCardControllerTest {
@Test
public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() {
mResolver.insert(CardContentProvider.URI, generateOneRow());
mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
@@ -109,7 +109,7 @@ public class SliceContextualCardControllerTest {
@Test
@Config(qualifiers = "mcc999")
public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() {
mResolver.insert(CardContentProvider.URI, generateOneRow());
mResolver.insert(CardContentProvider.REFRESH_CARD_URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());

View File

@@ -87,7 +87,7 @@ public class ChooseLockPasswordTest {
@Test
public void intentBuilder_setPassword_shouldAddExtras() {
Intent intent = new IntentBuilder(application)
.setPassword("password")
.setPassword("password".getBytes())
.setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)
.setUserId(123)
.build();
@@ -95,9 +95,9 @@ public class ChooseLockPasswordTest {
assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true))
.named("EXTRA_KEY_HAS_CHALLENGE")
.isFalse();
assertThat(intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
assertThat(intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.named("EXTRA_KEY_PASSWORD")
.isEqualTo("password");
.isEqualTo("password".getBytes());
assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0))
.named("PASSWORD_TYPE_KEY")
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
@@ -366,7 +366,9 @@ public class ChooseLockPasswordTest {
intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity);
ChooseLockPassword activity = buildChooseLockPasswordActivity(intent);
ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(activity);
int validateResult = fragment.validatePassword(userEnteredPassword);
byte[] userEnteredPasswordBytes = userEnteredPassword != null
? userEnteredPassword.getBytes() : null;
int validateResult = fragment.validatePassword(userEnteredPasswordBytes);
String[] messages = fragment.convertErrorCodeToMessages(validateResult);
assertThat(messages).asList().containsExactly((Object[]) expectedValidationResult);

View File

@@ -52,7 +52,7 @@ public class ChooseLockPatternTest {
@Test
public void intentBuilder_setPattern_shouldAddExtras() {
Intent intent = new IntentBuilder(application)
.setPattern("pattern")
.setPattern("pattern".getBytes())
.setUserId(123)
.build();
@@ -61,9 +61,9 @@ public class ChooseLockPatternTest {
.named("EXTRA_KEY_HAS_CHALLENGE")
.isFalse();
assertThat(intent
.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.named("EXTRA_KEY_PASSWORD")
.isEqualTo("pattern");
.isEqualTo("pattern".getBytes());
assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0))
.named("EXTRA_USER_ID")
.isEqualTo(123);

View File

@@ -124,6 +124,18 @@ public class PermissionBarChartPreferenceControllerTest {
verify(mPreference).initializeBarChart(any(BarChartInfo.class));
}
@Test
public void displayPreference_usageInfosSet_shouldSetBarViewInfos() {
final RuntimePermissionUsageInfo info1 =
new RuntimePermissionUsageInfo("permission 1", 10);
mController.mOldUsageInfos.add(info1);
mController.displayPreference(mScreen);
verify(mPreference).setBarViewInfos(any(BarViewInfo[].class));
verify(mPreference).initializeBarChart(any(BarChartInfo.class));
}
@Test
public void onPermissionUsageResult_differentPermissionResultSet_shouldSetBarViewInfos() {
final List<RuntimePermissionUsageInfo> infos1 = new ArrayList<>();
@@ -159,7 +171,7 @@ public class PermissionBarChartPreferenceControllerTest {
}
@Test
public void onStart_permissionHubEnabled_shouldShowProgressBar() {
public void onStart_usageInfosNotSetAndPermissionHubEnabled_shouldShowProgressBar() {
DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE,
DeviceConfig.Privacy.PROPERTY_PERMISSIONS_HUB_ENABLED, "true", true);
mController.displayPreference(mScreen);
@@ -170,6 +182,21 @@ public class PermissionBarChartPreferenceControllerTest {
verify(mPreference).updateLoadingState(true /* isLoading */);
}
@Test
public void onStart_usageInfosSetAndPermissionHubEnabled_shouldNotUpdatePrefLoadingState() {
DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE,
DeviceConfig.Privacy.PROPERTY_PERMISSIONS_HUB_ENABLED, "true", true);
final RuntimePermissionUsageInfo info1 =
new RuntimePermissionUsageInfo("permission 1", 10);
mController.mOldUsageInfos.add(info1);
mController.displayPreference(mScreen);
mController.onStart();
verify(mFragment).setLoadingEnabled(true /* enabled */);
verify(mPreference).updateLoadingState(false /* isLoading */);
}
@Test
public void onStart_permissionHubDisabled_shouldNotShowProgressBar() {
DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE,

View File

@@ -253,6 +253,18 @@ public class SliceTester {
assertThat(hasText(sliceItems, subtitle, null /* hints */)).isTrue();
}
/**
* Assert no slice item contains subtitle.
*
* @param sliceItems All slice items of a Slice.
* @param subtitle Subtitle for asserting.
*/
public static void assertNoSliceItemContainsSubtitle(List<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) {

View File

@@ -66,12 +66,12 @@ public class ShadowLockPatternUtils {
}
@Implementation
protected byte[] getPasswordHistoryHashFactor(String currentPassword, int userId) {
protected byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) {
return null;
}
@Implementation
protected boolean checkPasswordHistory(String passwordToCheck, byte[] hashFactor, int userId) {
protected boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) {
return false;
}
}

View File

@@ -26,6 +26,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.annotation.Resetter;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +39,8 @@ import java.util.Set;
@Implements(value = UserManager.class)
public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
private static boolean sIsSupportsMultipleUsers;
private final List<String> mRestrictions = new ArrayList<>();
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
@@ -50,6 +53,11 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
mUserProfileInfos.add(userInfo);
}
@Resetter
public static void reset() {
sIsSupportsMultipleUsers = false;
}
@Implementation
protected List<UserInfo> getProfiles(@UserIdInt int userHandle) {
return mUserProfileInfos;
@@ -124,4 +132,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
public void setUserSwitcherEnabled(boolean userSwitchEnabled) {
mUserSwitchEnabled = userSwitchEnabled;
}
@Implementation
protected static boolean supportsMultipleUsers() {
return sIsSupportsMultipleUsers;
}
public void setSupportsMultipleUsers(boolean supports) {
sIsSupportsMultipleUsers = supports;
}
}

View File

@@ -38,6 +38,7 @@ public class ShadowUtils {
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 @@ public class ShadowUtils {
}
sAppNameMap.put(packageName, appLabel);
}
@Implementation
protected static boolean isSystemAlertWindowEnabled(Context context) {
return sIsSystemAlertWindowEnabled;
}
public static void setIsSystemAlertWindowEnabled(boolean enabled) {
sIsSystemAlertWindowEnabled = enabled;
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.users;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class})
public class MultiUserSwitchBarControllerTest {
private Context mContext;
private ShadowUserManager mUserManager;
private SwitchBarController mSwitchBarController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mUserManager = ShadowUserManager.getShadow();
mSwitchBarController = spy(new SwitchBarController(new SwitchBar(mContext)));
mUserManager.setSupportsMultipleUsers(true);
}
@After
public void tearDown() {
ShadowUserManager.reset();
}
@Test
public void onStart_disallowUserSwitch_shouldSetDisabledByAdmin() {
mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
UserManager.DISALLOW_USER_SWITCH, true);
final MultiUserSwitchBarController controller = new MultiUserSwitchBarController(mContext,
mSwitchBarController, null);
verify(mSwitchBarController).setDisabledByAdmin(any());
}
@Test
public void onStart_allowUserSwitch_shouldNotSetDisabledByAdmin() {
mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
UserManager.DISALLOW_USER_SWITCH, false);
final MultiUserSwitchBarController controller = new MultiUserSwitchBarController(mContext,
mSwitchBarController, null);
verify(mSwitchBarController, never()).setDisabledByAdmin(any());
}
}

View File

@@ -429,7 +429,7 @@ public class WifiDetailPreferenceControllerTest {
@Test
public void linkSpeedPref_shouldNotShowIfNotSet() {
when(mockWifiInfo.getTxLinkSpeedMbps()).thenReturn(-1);
when(mockWifiInfo.getTxLinkSpeedMbps()).thenReturn(WifiInfo.LINK_SPEED_UNKNOWN);
displayAndResume();
@@ -447,7 +447,7 @@ public class WifiDetailPreferenceControllerTest {
@Test
public void rxLinkSpeedPref_shouldNotShowIfNotSet() {
when(mockWifiInfo.getRxLinkSpeedMbps()).thenReturn(-1);
when(mockWifiInfo.getRxLinkSpeedMbps()).thenReturn(WifiInfo.LINK_SPEED_UNKNOWN);
displayAndResume();

View File

@@ -21,6 +21,7 @@ import static android.app.slice.SliceItem.FORMAT_SLICE;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
import static com.android.settings.wifi.slice.WifiSlice.WifiScanWorker;
import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +33,8 @@ import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import androidx.core.graphics.drawable.IconCompat;
@@ -44,24 +47,33 @@ import androidx.slice.core.SliceQuery;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.testutils.SliceTester;
import com.android.settingslib.wifi.AccessPoint;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class WifiSliceTest {
private static final String AP1_NAME = "ap1";
private static final String AP2_NAME = "ap2";
private Context mContext;
private ContentResolver mResolver;
private WifiManager mWifiManager;
private WifiSlice mWifiSlice;
private WifiSlice.WifiScanWorker mWifiScanWorker;
private WifiScanWorker mWifiScanWorker;
@Before
public void setUp() {
@@ -75,7 +87,7 @@ public class WifiSliceTest {
mWifiManager.setWifiEnabled(true);
mWifiSlice = new WifiSlice(mContext);
mWifiScanWorker = new WifiSlice.WifiScanWorker(mContext, WIFI_SLICE_URI);
mWifiScanWorker = new WifiScanWorker(mContext, WIFI_SLICE_URI);
}
@Test
@@ -122,6 +134,107 @@ public class WifiSliceTest {
mContext.getString(R.string.wifi_empty_list_wifi_on));
}
private AccessPoint createAccessPoint(String name, boolean active, boolean reachable) {
final AccessPoint accessPoint = mock(AccessPoint.class);
doReturn(name).when(accessPoint).getConfigName();
doReturn(active).when(accessPoint).isActive();
doReturn(reachable).when(accessPoint).isReachable();
if (active) {
final NetworkInfo networkInfo = mock(NetworkInfo.class);
doReturn(networkInfo).when(accessPoint).getNetworkInfo();
doReturn(NetworkInfo.State.CONNECTED).when(networkInfo).getState();
}
return accessPoint;
}
private void setWorkerResults(AccessPoint... accessPoints) {
final ArrayList<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 @@ public class WifiSliceTest {
verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
}
@Implements(SliceBackgroundWorker.class)
public static class ShadowSliceBackgroundWorker {
private static WifiScanWorker mWifiScanWorker = mock(WifiScanWorker.class);
@Implementation
public static SliceBackgroundWorker getInstance(Uri uri) {
return mWifiScanWorker;
}
}
}

View File

@@ -52,7 +52,9 @@ public class HomepageDisplayTests {
"Display",
"Sound",
"Storage",
"Security & location",
"Security",
"Location",
"Privacy",
"Accounts",
"Accessibility",
"System"