Snap for 9990577 from eea8283783 to udc-release

Change-Id: Ic8b5ad608ab74ebf4cc91e164c4a01751667577e
This commit is contained in:
Android Build Coastguard Worker
2023-04-22 01:31:50 +00:00
22 changed files with 442 additions and 710 deletions

View File

@@ -1003,6 +1003,22 @@
android:value="true"/>
</activity>
<activity
android:name=".Settings$NavigationModeSettingsActivity"
android:label="@string/system_navigation_title"
android:exported="true">
<intent-filter>
<action android:name="com.android.settings.NAVIGATION_MODE_SETTINGS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.SystemNavigationGestureSettings"/>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_system"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true"/>
</activity>
<activity
android:name=".Settings$RegionalPreferencesActivity"
android:label="@string/regional_preferences_title"
@@ -3477,11 +3493,24 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnSettings" />
android:value="com.android.settings.applications.manageapplications.ManageApplications" />
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity>
<activity
android:name="Settings$AppTurnScreenOnSettingsActivity"
android:exported="true"
android:label="@string/turn_screen_on_title">
<intent-filter android:priority="1">
<action android:name="android.settings.TURN_SCREEN_ON_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnDetails"/>
</activity>
<activity
android:name="Settings$InteractAcrossProfilesSettingsActivity"
android:exported="true"

View File

@@ -13,44 +13,48 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/admin_details_dialog_padding"
android:paddingStart="@dimen/admin_details_dialog_padding"
android:paddingEnd="@dimen/admin_details_dialog_padding"
android:paddingBottom="@dimen/admin_details_dialog_padding_bottom"
android:orientation="vertical"
android:layoutDirection="locale"
android:textDirection="locale">
android:fadeScrollbars="false"
android:scrollbarStyle="outsideOverlay"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/admin_details_dialog_padding"
android:paddingStart="@dimen/admin_details_dialog_padding"
android:paddingEnd="@dimen/admin_details_dialog_padding"
android:paddingBottom="@dimen/admin_details_dialog_padding_bottom"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding">
<ImageView
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
android:src="@drawable/ic_settings_language"
android:tint="#4F8438"
android:contentDescription="@null"/>
<TextView
android:id="@+id/dialog_title"
android:layout_width="wrap_content"
android:layoutDirection="locale"
android:textDirection="locale">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="vertical"
android:gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.AdminDialogTitle"
android:textAlignment="textStart"/>
</LinearLayout>
android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding">
<ImageView
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
android:src="@drawable/ic_settings_language"
android:tint="#4F8438"
android:contentDescription="@null"/>
<TextView
android:id="@+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:textSize="20sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"/>
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -60,10 +64,11 @@
android:id="@+id/dialog_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:maxLength="200"
android:autoLink="email|phone|web"
android:textColor="?android:attr/textColorSecondary"
android:textAlignment="textStart"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -195,7 +195,11 @@
android:key="turn_screen_on"
android:title="@string/turn_screen_on_title"
android:order="-200"
android:fragment="com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnSettings" />
android:fragment="com.android.settings.applications.manageapplications.ManageApplications">
<extra
android:name="classname"
android:value="com.android.settings.Settings$TurnScreenOnSettingsActivity" />
</Preference>
<Preference
android:key="special_access_more"

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2022 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="turn_screen_on_screen"
android:title="@string/turn_screen_on_title"
settings:searchable="false" />

View File

@@ -135,6 +135,8 @@ public class Settings extends SettingsActivity {
/** Activity for the regional preferences settings. */
public static class RegionalPreferencesActivity extends SettingsActivity { /* empty */ }
public static class KeyboardSettingsActivity extends SettingsActivity { /* empty */ }
/** Activity for the navigation mode settings. */
public static class NavigationModeSettingsActivity extends SettingsActivity { /* empty */ }
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
public static class DarkThemeSettingsActivity extends SettingsActivity { /* empty */ }
public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ }
@@ -350,6 +352,7 @@ public class Settings extends SettingsActivity {
public static class PremiumSmsAccessActivity extends SettingsActivity { /* empty */ }
public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
public static class TurnScreenOnSettingsActivity extends SettingsActivity { /* empty */ }
public static class AppTurnScreenOnSettingsActivity extends SettingsActivity { /* empty */ }
public static class AppPictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenAccessDetailSettingsActivity extends SettingsActivity {}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2023 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.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import java.util.List;
/**
* Connects app op info to the ApplicationsState. Extends {@link AppStateAppOpsBridge} to tailor
* to the semantics of {@link Manifest.permission#TURN_SCREEN_ON}.
* Also provides app filters that can use the info.
*/
public class AppStateTurnScreenOnBridge extends AppStateAppOpsBridge {
private static final String APP_OP_STR = AppOpsManager.OPSTR_TURN_SCREEN_ON;
private static final String[] PERMISSIONS = {
Manifest.permission.TURN_SCREEN_ON
};
private AppOpsManager mAppOpsManager;
public AppStateTurnScreenOnBridge(Context context, ApplicationsState appState,
Callback callback) {
super(context, appState, callback, AppOpsManager.strOpToOp(APP_OP_STR), PERMISSIONS);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
}
@Override
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
app.extraInfo = getPermissionInfo(pkg, uid);
}
@Override
protected void loadAllExtraInfo() {
super.loadAllExtraInfo();
final List<AppEntry> apps = mAppSession.getAllApps();
for (AppEntry app : apps) {
if (app.extraInfo instanceof PermissionState) {
((PermissionState) app.extraInfo).appOpMode = mAppOpsManager.unsafeCheckOpNoThrow(
APP_OP_STR, app.info.uid, app.info.packageName);
}
}
}
@Override
public PermissionState getPermissionInfo(String pkg, int uid) {
PermissionState ps = super.getPermissionInfo(pkg, uid);
ps.appOpMode = mAppOpsManager.unsafeCheckOpNoThrow(APP_OP_STR, uid, pkg);
return ps;
}
public static final AppFilter FILTER_TURN_SCREEN_ON_APPS = new AppFilter() {
@Override
public void init() {
}
@Override
public boolean filterApp(AppEntry info) {
// If extraInfo != null, it means that the app has declared
// Manifest.permission.TURN_SCREEN_ON and therefore it should appear on our
// list
return info.extraInfo != null;
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2023 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.
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess.turnscreenon;
package com.android.settings.applications.appinfo;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.OP_TURN_SCREEN_ON;
import android.app.AppOpsManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
@@ -29,41 +31,51 @@ import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge;
import com.android.settings.applications.AppStateTurnScreenOnBridge;
import com.android.settingslib.applications.ApplicationsState;
/**
* Detail page for turn screen on special app access.
*/
public class TurnScreenOnDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
public class TurnScreenOnDetails extends AppInfoWithHeader implements OnPreferenceChangeListener {
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private SwitchPreference mSwitchPref;
private AppStateTurnScreenOnBridge mAppBridge;
private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref;
private AppStateAppOpsBridge.PermissionState mPermissionState;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppOpsManager = this.getSystemService(AppOpsManager.class);
final Context context = getActivity();
mAppBridge = new AppStateTurnScreenOnBridge(context, mState, /*callback=*/ null);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
// find preferences
addPreferencesFromResource(R.xml.turn_screen_on_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
// set title/summary for all of them
mSwitchPref.setTitle(R.string.allow_turn_screen_on);
// install event listeners
mSwitchPref.setOnPreferenceChangeListener(this);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean checked = (Boolean) newValue;
if (preference == mSwitchPref) {
setTurnScreenOnAppOp(mPackageInfo.applicationInfo.uid, mPackageName,
(Boolean) newValue);
if (mPermissionState != null && checked != mPermissionState.isPermissible()) {
if (Settings.TurnScreenOnSettingsActivity.class.getName().equals(
getIntent().getComponent().getClassName())) {
setResult(checked ? RESULT_OK : RESULT_CANCELED);
}
setCanTurnScreenOn(checked);
refreshUi();
}
return true;
}
return false;
@@ -71,9 +83,13 @@ public class TurnScreenOnDetails extends AppInfoWithHeader
@Override
protected boolean refreshUi() {
boolean isAllowed = isTurnScreenOnAllowed(mAppOpsManager,
mPackageInfo.applicationInfo.uid, mPackageName);
mSwitchPref.setChecked(isAllowed);
if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
return false;
}
mPermissionState = mAppBridge.getPermissionInfo(mPackageName,
mPackageInfo.applicationInfo.uid);
mSwitchPref.setEnabled(mPermissionState.permissionDeclared);
mSwitchPref.setChecked(mPermissionState.isPermissible());
return true;
}
@@ -91,28 +107,24 @@ public class TurnScreenOnDetails extends AppInfoWithHeader
* Sets whether the app associated with the given {@code packageName} is allowed to turn the
* screen on.
*/
void setTurnScreenOnAppOp(int uid, String packageName, boolean value) {
final int newMode = value ? MODE_ALLOWED : MODE_ERRORED;
mAppOpsManager.setMode(OP_TURN_SCREEN_ON, uid, packageName, newMode);
}
/**
* @return whether the app associated with the given {@code packageName} is allowed to turn the
* screen on.
*/
static boolean isTurnScreenOnAllowed(AppOpsManager appOpsManager, int uid, String packageName) {
return appOpsManager.checkOpNoThrow(OP_TURN_SCREEN_ON, uid, packageName) == MODE_ALLOWED;
void setCanTurnScreenOn(boolean newState) {
mAppOpsManager.setUidMode(AppOpsManager.OPSTR_TURN_SCREEN_ON,
mPackageInfo.applicationInfo.uid, newState ? MODE_ALLOWED : MODE_ERRORED);
}
/**
* @return the summary for the current state of whether the app associated with the given
* packageName is allowed to turn the screen on.
*/
public static int getPreferenceSummary(AppOpsManager appOpsManager, int uid,
String packageName) {
final boolean enabled = TurnScreenOnDetails.isTurnScreenOnAllowed(appOpsManager, uid,
packageName);
return enabled ? R.string.app_permission_summary_allowed
public static int getSummary(Context context, ApplicationsState.AppEntry entry) {
final AppStateAppOpsBridge.PermissionState state;
if (entry.extraInfo instanceof AppStateAppOpsBridge.PermissionState) {
state = (AppStateAppOpsBridge.PermissionState) entry.extraInfo;
} else {
state = new AppStateTurnScreenOnBridge(context, /*appState=*/ null,
/*callback=*/ null).getPermissionInfo(entry.info.packageName, entry.info.uid);
}
return state.isPermissible() ? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed;
}
}

View File

@@ -30,6 +30,7 @@ import com.android.settings.applications.AppStateMediaManagementAppsBridge;
import com.android.settings.applications.AppStateNotificationBridge;
import com.android.settings.applications.AppStateOverlayBridge;
import com.android.settings.applications.AppStatePowerBridge;
import com.android.settings.applications.AppStateTurnScreenOnBridge;
import com.android.settings.applications.AppStateUsageBridge;
import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.nfc.AppStateNfcTagAppsBridge;
@@ -67,6 +68,7 @@ public class AppFilterRegistry {
FILTER_LONG_BACKGROUND_TASKS,
FILTER_APPS_CLONE,
FILTER_APPS_NFC_TAG,
FILTER_APPS_TURN_SCREEN_ON,
})
@interface FilterType {}
@@ -98,8 +100,9 @@ public class AppFilterRegistry {
public static final int FILTER_LONG_BACKGROUND_TASKS = 24;
public static final int FILTER_APPS_CLONE = 25;
public static final int FILTER_APPS_NFC_TAG = 26;
private static final int NUM_FILTER_ENTRIES = 27;
// Next id: 27. If you add an entry here, please change NUM_FILTER_ENTRIES.
public static final int FILTER_APPS_TURN_SCREEN_ON = 27;
private static final int NUM_FILTER_ENTRIES = 28;
// Next id: 28. If you add an entry here, please change NUM_FILTER_ENTRIES.
private static AppFilterRegistry sRegistry;
@@ -271,6 +274,12 @@ public class AppFilterRegistry {
AppStateNfcTagAppsBridge.FILTER_APPS_NFC_TAG,
FILTER_APPS_NFC_TAG,
R.string.change_nfc_tag_apps_title);
// Apps that are allowed to turn the screen on.
mFilters[FILTER_APPS_TURN_SCREEN_ON] = new AppFilterItem(
AppStateTurnScreenOnBridge.FILTER_TURN_SCREEN_ON_APPS,
FILTER_APPS_TURN_SCREEN_ON,
R.string.turn_screen_on_title);
}
public static AppFilterRegistry getInstance() {
@@ -313,6 +322,8 @@ public class AppFilterRegistry {
return FILTER_APPS_CLONE;
case ManageApplications.LIST_TYPE_NFC_TAG_APPS:
return FILTER_APPS_NFC_TAG;
case ManageApplications.LIST_TYPE_TURN_SCREEN_ON:
return FILTER_APPS_TURN_SCREEN_ON;
default:
return FILTER_APPS_ALL;
}

View File

@@ -110,6 +110,7 @@ import com.android.settings.Settings.MediaManagementAppsActivity;
import com.android.settings.Settings.NotificationAppListActivity;
import com.android.settings.Settings.NotificationReviewPermissionsActivity;
import com.android.settings.Settings.OverlaySettingsActivity;
import com.android.settings.Settings.TurnScreenOnSettingsActivity;
import com.android.settings.Settings.UsageAccessSettingsActivity;
import com.android.settings.Settings.WriteSettingsActivity;
import com.android.settings.SettingsActivity;
@@ -129,6 +130,7 @@ import com.android.settings.applications.AppStateNotificationBridge;
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
import com.android.settings.applications.AppStateOverlayBridge;
import com.android.settings.applications.AppStatePowerBridge;
import com.android.settings.applications.AppStateTurnScreenOnBridge;
import com.android.settings.applications.AppStateUsageBridge;
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.applications.AppStateWriteSettingsBridge;
@@ -142,6 +144,7 @@ import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.LongBackgroundTasksDetails;
import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
import com.android.settings.applications.appinfo.TurnScreenOnDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
@@ -268,6 +271,7 @@ public class ManageApplications extends InstrumentedFragment
public static final int LIST_TYPE_LONG_BACKGROUND_TASKS = 16;
public static final int LIST_TYPE_CLONED_APPS = 17;
public static final int LIST_TYPE_NFC_TAG_APPS = 18;
public static final int LIST_TYPE_TURN_SCREEN_ON = 19;
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
@@ -569,6 +573,8 @@ public class ManageApplications extends InstrumentedFragment
return SettingsEnums.CLONED_APPS;
case LIST_TYPE_NFC_TAG_APPS:
return SettingsEnums.CONFIG_NFC_TAG_APP_PREF;
case LIST_TYPE_TURN_SCREEN_ON:
return SettingsEnums.SETTINGS_TURN_SCREEN_ON_ACCESS;
default:
return SettingsEnums.PAGE_UNKNOWN;
}
@@ -739,6 +745,9 @@ public class ManageApplications extends InstrumentedFragment
startAppInfoFragment(ChangeNfcTagAppsStateDetails.class,
R.string.change_nfc_tag_apps_title);
break;
case LIST_TYPE_TURN_SCREEN_ON:
startAppInfoFragment(TurnScreenOnDetails.class, R.string.turn_screen_on_title);
break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
// app. Maybe when they load the list of apps that contains managed profile apps.
@@ -1066,6 +1075,8 @@ public class ManageApplications extends InstrumentedFragment
screenTitle = R.string.cloned_apps_dashboard_title;
} else if (className.equals(ChangeNfcTagAppsActivity.class.getName())) {
screenTitle = R.string.change_nfc_tag_apps_title;
} else if (className.equals(TurnScreenOnSettingsActivity.class.getName())) {
screenTitle = R.string.turn_screen_on_title;
} else {
if (screenTitle == -1) {
screenTitle = R.string.all_apps;
@@ -1276,6 +1287,8 @@ public class ManageApplications extends InstrumentedFragment
mExtraInfoBridge = new AppStateClonedAppsBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_NFC_TAG_APPS) {
mExtraInfoBridge = new AppStateNfcTagAppsBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_TURN_SCREEN_ON) {
mExtraInfoBridge = new AppStateTurnScreenOnBridge(mContext, mState, this);
} else {
mExtraInfoBridge = null;
}
@@ -1830,6 +1843,9 @@ public class ManageApplications extends InstrumentedFragment
holder.setSummary(
ChangeNfcTagAppsStateDetails.getSummary(mContext, entry));
break;
case LIST_TYPE_TURN_SCREEN_ON:
holder.setSummary(TurnScreenOnDetails.getSummary(mContext, entry));
break;
default:
holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
break;

View File

@@ -33,6 +33,7 @@ import com.android.settings.Settings.NotificationAppListActivity
import com.android.settings.Settings.NotificationReviewPermissionsActivity
import com.android.settings.Settings.OverlaySettingsActivity
import com.android.settings.Settings.StorageUseActivity
import com.android.settings.Settings.TurnScreenOnSettingsActivity
import com.android.settings.Settings.UsageAccessSettingsActivity
import com.android.settings.Settings.WriteSettingsActivity
import com.android.settings.applications.appinfo.AppLocaleDetails
@@ -51,6 +52,7 @@ import com.android.settings.applications.manageapplications.ManageApplications.L
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_OVERLAY
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_STORAGE
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_TURN_SCREEN_ON
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_USAGE_ACCESS
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WIFI_ACCESS
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WRITE_SETTINGS
@@ -88,6 +90,7 @@ object ManageApplicationsUtil {
LongBackgroundTasksActivity::class to LIST_TYPE_LONG_BACKGROUND_TASKS,
ClonedAppsListActivity::class to LIST_TYPE_CLONED_APPS,
ChangeNfcTagAppsActivity::class to LIST_TYPE_NFC_TAG_APPS,
TurnScreenOnSettingsActivity::class to LIST_TYPE_TURN_SCREEN_ON,
)
@JvmField

View File

@@ -1,215 +0,0 @@
/*
* Copyright (C) 2022 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.turnscreenon;
import android.Manifest;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.IconDrawableFactory;
import android.util.Pair;
import android.view.View;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.EmptyTextSettings;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.widget.AppPreference;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* Settings page for providing special app access to turn the screen of the device on.
*/
@SearchIndexable
public class TurnScreenOnSettings extends EmptyTextSettings {
@VisibleForTesting
static final List<String> IGNORE_PACKAGE_LIST = new ArrayList<>();
static {
IGNORE_PACKAGE_LIST.add(Utils.SYSTEMUI_PACKAGE_NAME);
}
/**
* Comparator by name, then user id.
* {@see PackageItemInfo#DisplayNameComparator}
*/
static class AppComparator implements Comparator<Pair<ApplicationInfo, Integer>> {
private final Collator mCollator = Collator.getInstance();
private final PackageManager mPm;
AppComparator(PackageManager pm) {
mPm = pm;
}
public final int compare(Pair<ApplicationInfo, Integer> a,
Pair<ApplicationInfo, Integer> b) {
CharSequence sa = a.first.loadLabel(mPm);
if (sa == null) sa = a.first.name;
CharSequence sb = b.first.loadLabel(mPm);
if (sb == null) sb = b.first.name;
int nameCmp = mCollator.compare(sa.toString(), sb.toString());
if (nameCmp != 0) {
return nameCmp;
} else {
return a.second - b.second;
}
}
}
private AppOpsManager mAppOpsManager;
private Context mContext;
private PackageManager mPackageManager;
private UserManager mUserManager;
private IconDrawableFactory mIconDrawableFactory;
public TurnScreenOnSettings() {
// Do nothing
}
public TurnScreenOnSettings(PackageManager pm, UserManager um) {
mPackageManager = pm;
mUserManager = um;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mContext = getActivity();
mPackageManager = mContext.getPackageManager();
mUserManager = mContext.getSystemService(UserManager.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
}
@Override
public void onResume() {
super.onResume();
// Clear the prefs
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
// Fetch the set of applications for each profile which have the permission required to turn
// the screen on with a wake lock.
final ArrayList<Pair<ApplicationInfo, Integer>> apps = collectTurnScreenOnApps(
UserHandle.myUserId());
apps.sort(new AppComparator(mPackageManager));
// Rebuild the list of prefs
final Context prefContext = getPrefContext();
for (final Pair<ApplicationInfo, Integer> appData : apps) {
final ApplicationInfo appInfo = appData.first;
final int userId = appData.second;
final UserHandle user = UserHandle.of(userId);
final String packageName = appInfo.packageName;
final CharSequence label = appInfo.loadLabel(mPackageManager);
final Preference pref = new AppPreference(prefContext);
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appInfo, userId));
pref.setTitle(mPackageManager.getUserBadgedLabel(label, user));
pref.setSummary(TurnScreenOnDetails.getPreferenceSummary(mAppOpsManager,
appInfo.uid, packageName));
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
AppInfoBase.startAppInfoFragment(TurnScreenOnDetails.class,
getString(R.string.turn_screen_on_title),
packageName, appInfo.uid,
TurnScreenOnSettings.this, -1, getMetricsCategory());
return true;
}
});
screen.addPreference(pref);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setEmptyText(R.string.no_applications);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.turn_screen_on_settings;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_TURN_SCREEN_ON_ACCESS;
}
/**
* @return the list of applications for the given user and all their profiles that can turn on
* the screen with wake locks.
*/
@VisibleForTesting
ArrayList<Pair<ApplicationInfo, Integer>> collectTurnScreenOnApps(int userId) {
final ArrayList<Pair<ApplicationInfo, Integer>> apps = new ArrayList<>();
final ArrayList<Integer> userIds = new ArrayList<>();
for (UserInfo user : mUserManager.getProfiles(userId)) {
userIds.add(user.id);
}
for (int id : userIds) {
final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
/* flags= */ 0, id);
for (PackageInfo packageInfo : installedPackages) {
if (hasTurnScreenOnPermission(mPackageManager, packageInfo.packageName)) {
apps.add(new Pair<>(packageInfo.applicationInfo, id));
}
}
}
return apps;
}
/**
* @return true if the package has the permission to turn the screen on.
*/
@VisibleForTesting
static boolean hasTurnScreenOnPermission(PackageManager packageManager, String packageName) {
if (IGNORE_PACKAGE_LIST.contains(packageName)) {
return false;
}
return packageManager.checkPermission(Manifest.permission.TURN_SCREEN_ON, packageName)
== PackageManager.PERMISSION_GRANTED;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.turn_screen_on_settings);
}

View File

@@ -593,10 +593,16 @@ public class FingerprintSettings extends SubSettings {
}
private void updateAddPreference() {
if (getActivity() == null) return; // Activity went away
if (getActivity() == null) {
return; // Activity went away
}
final Preference addPreference = findPreference(KEY_FINGERPRINT_ADD);
if (addPreference == null) {
return; // b/275519315 Skip if updateAddPreference() invoke before addPreference()
}
/* Disable preference if too many fingerprints added */
final int max = getContext().getResources().getInteger(
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);

View File

@@ -50,6 +50,7 @@ import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.LongBackgroundTasksDetails;
import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
import com.android.settings.applications.appinfo.TurnScreenOnDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.applications.appops.BackgroundCheckSummary;
import com.android.settings.applications.assist.ManageAssist;
@@ -62,8 +63,6 @@ import com.android.settings.applications.specialaccess.notificationaccess.Notifi
import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails;
import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings;
import com.android.settings.applications.specialaccess.premiumsms.PremiumSmsAccess;
import com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnDetails;
import com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnSettings;
import com.android.settings.applications.specialaccess.vrlistener.VrListenerSettings;
import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
import com.android.settings.backup.PrivacySettings;
@@ -368,7 +367,6 @@ public class SettingsGateway {
OneHandedSettings.class.getName(),
MobileNetworkSettings.class.getName(),
AppLocaleDetails.class.getName(),
TurnScreenOnSettings.class.getName(),
TurnScreenOnDetails.class.getName(),
NfcAndPaymentFragment.class.getName(),
ColorAndMotionFragment.class.getName(),
@@ -419,5 +417,6 @@ public class SettingsGateway {
Settings.ModuleLicensesActivity.class.getName(),
UserBackupSettingsActivity.class.getName(),
Settings.MemtagPageActivity.class.getName(),
Settings.NavigationModeSettingsActivity.class.getName(),
};
}

View File

@@ -16,17 +16,18 @@
package com.android.settings.development;
import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.internal.display.RefreshRateSettingsUtils;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
@@ -34,12 +35,6 @@ import com.android.settingslib.development.DeveloperOptionsPreferenceController;
public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
@VisibleForTesting
static float DEFAULT_REFRESH_RATE = 60f;
@VisibleForTesting
static float NO_CONFIG = 0f;
@VisibleForTesting
float mPeakRefreshRate;
@@ -48,17 +43,8 @@ public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPr
public ForcePeakRefreshRatePreferenceController(Context context) {
super(context);
final DisplayManager dm = context.getSystemService(DisplayManager.class);
final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
if (display == null) {
Log.w(TAG, "No valid default display device");
mPeakRefreshRate = DEFAULT_REFRESH_RATE;
} else {
mPeakRefreshRate = findPeakRefreshRate(display.getSupportedModes());
}
mPeakRefreshRate =
RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(context);
Log.d(TAG, "DEFAULT_REFRESH_RATE : " + DEFAULT_REFRESH_RATE
+ " mPeakRefreshRate : " + mPeakRefreshRate);
}
@@ -99,34 +85,20 @@ public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPr
@Override
protected void onDeveloperOptionsSwitchDisabled() {
super.onDeveloperOptionsSwitchDisabled();
Settings.System.putFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, 0);
((SwitchPreference) mPreference).setChecked(false);
}
@VisibleForTesting
void forcePeakRefreshRate(boolean enable) {
final float peakRefreshRate = enable ? mPeakRefreshRate : NO_CONFIG;
Settings.System.putFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, peakRefreshRate);
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, enable ? 1 : 0);
}
boolean isForcePeakRefreshRateEnabled() {
final float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
return peakRefreshRate >= mPeakRefreshRate;
}
private float findPeakRefreshRate(Display.Mode[] modes) {
float peakRefreshRate = DEFAULT_REFRESH_RATE;
for (Display.Mode mode : modes) {
if (Math.round(mode.getRefreshRate()) > peakRefreshRate) {
peakRefreshRate = mode.getRefreshRate();
}
}
return peakRefreshRate;
return Settings.System.getInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, 0) == 1;
}
}

View File

@@ -16,18 +16,20 @@
package com.android.settings.display;
import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.display.RefreshRateSettingsUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -39,8 +41,6 @@ import java.util.concurrent.Executor;
public class PeakRefreshRatePreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop {
@VisibleForTesting static float DEFAULT_REFRESH_RATE = 60f;
@VisibleForTesting float mPeakRefreshRate;
private static final String TAG = "RefreshRatePrefCtr";
@@ -65,17 +65,8 @@ public class PeakRefreshRatePreferenceController extends TogglePreferenceControl
updateState(mPreference);
}
};
final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
if (display == null) {
Log.w(TAG, "No valid default display device");
mPeakRefreshRate = DEFAULT_REFRESH_RATE;
} else {
mPeakRefreshRate = findPeakRefreshRate(display.getSupportedModes());
}
mPeakRefreshRate =
RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(context);
Log.d(
TAG,
"DEFAULT_REFRESH_RATE : "
@@ -106,21 +97,15 @@ public class PeakRefreshRatePreferenceController extends TogglePreferenceControl
@Override
public boolean isChecked() {
final float peakRefreshRate =
Settings.System.getFloat(
mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE,
getDefaultPeakRefreshRate());
return Math.round(peakRefreshRate) == Math.round(mPeakRefreshRate);
return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY,
0) == 1;
}
@Override
public boolean setChecked(boolean isChecked) {
final float peakRefreshRate = isChecked ? mPeakRefreshRate : DEFAULT_REFRESH_RATE;
Log.d(TAG, "setChecked to : " + peakRefreshRate);
return Settings.System.putFloat(
mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, peakRefreshRate);
Log.d(TAG, "setChecked to : " + isChecked);
return Settings.System.putInt(
mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, isChecked ? 1 : 0);
}
@Override
@@ -138,17 +123,6 @@ public class PeakRefreshRatePreferenceController extends TogglePreferenceControl
mDeviceConfigDisplaySettings.stopListening();
}
@VisibleForTesting
float findPeakRefreshRate(Display.Mode[] modes) {
float peakRefreshRate = DEFAULT_REFRESH_RATE;
for (Display.Mode mode : modes) {
if (Math.round(mode.getRefreshRate()) > peakRefreshRate) {
peakRefreshRate = mode.getRefreshRate();
}
}
return peakRefreshRate;
}
private class DeviceConfigDisplaySettings
implements DeviceConfig.OnPropertiesChangedListener, Executor {
public void startListening() {
@@ -191,15 +165,4 @@ public class PeakRefreshRatePreferenceController extends TogglePreferenceControl
}
}
}
private float getDefaultPeakRefreshRate() {
float defaultPeakRefreshRate = mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) {
defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultPeakRefreshRate);
}
Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate);
return defaultPeakRefreshRate;
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import androidx.preference.SwitchPreference;
import com.android.settings.applications.AppStateAppOpsBridge;
import com.android.settings.applications.AppStateTurnScreenOnBridge;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class TurnScreenOnDetailsTest {
@Mock
private SwitchPreference mSwitchPref;
@Mock
private PackageInfo mPackageInfo;
@Mock
private AppStateTurnScreenOnBridge mAppStateBridge;
@Mock
private AppStateAppOpsBridge.PermissionState mPermissionState;
private final TurnScreenOnDetails mFragment = new TurnScreenOnDetails();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ReflectionHelpers.setField(mFragment, "mSwitchPref", mSwitchPref);
ReflectionHelpers.setField(mFragment, "mAppBridge", mAppStateBridge);
}
@Test
public void refreshUi_noPackageInfo_shouldReturnFalseAndNoCrash() {
mFragment.refreshUi();
assertThat(mFragment.refreshUi()).isFalse();
// should not crash
}
@Test
public void refreshUi_noApplicationInfo_shouldReturnFalseAndNoCrash() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mFragment.refreshUi();
assertThat(mFragment.refreshUi()).isFalse();
// should not crash
}
@Test
public void refreshUi_hasApplicationInfo_shouldReturnTrue() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mPackageInfo.applicationInfo = new ApplicationInfo();
when(mAppStateBridge.getPermissionInfo(nullable(String.class), anyInt()))
.thenReturn(mPermissionState);
mFragment.refreshUi();
assertThat(mFragment.refreshUi()).isTrue();
}
@Test
public void refreshUi_permissionNotDeclared_switchPreferenceDisabled() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mPackageInfo.applicationInfo = new ApplicationInfo();
when(mAppStateBridge.getPermissionInfo(nullable(String.class), anyInt()))
.thenReturn(mPermissionState);
mPermissionState.permissionDeclared = false;
mFragment.refreshUi();
verify(mSwitchPref).setEnabled(false);
}
@Test
public void refreshUi_permissionDeclared_switchPreferenceEnabled() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mPackageInfo.applicationInfo = new ApplicationInfo();
when(mAppStateBridge.getPermissionInfo(nullable(String.class), anyInt()))
.thenReturn(mPermissionState);
mPermissionState.permissionDeclared = true;
mFragment.refreshUi();
verify(mSwitchPref).setEnabled(true);
}
@Test
public void refreshUi_turnScreenOnAllowed_switchPreferenceChecked() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mPackageInfo.applicationInfo = new ApplicationInfo();
when(mAppStateBridge.getPermissionInfo(nullable(String.class), anyInt()))
.thenReturn(mPermissionState);
when(mPermissionState.isPermissible()).thenReturn(true);
mFragment.refreshUi();
verify(mSwitchPref).setChecked(true);
}
@Test
public void refreshUi_turnScreenOnDisallowed_switchPreferenceUnchecked() {
ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo);
mPackageInfo.applicationInfo = new ApplicationInfo();
when(mAppStateBridge.getPermissionInfo(nullable(String.class), anyInt()))
.thenReturn(mPermissionState);
when(mPermissionState.isPermissible()).thenReturn(false);
mFragment.refreshUi();
verify(mSwitchPref).setChecked(false);
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2022 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.turnscreenon;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.OP_TURN_SCREEN_ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class TurnScreenOnDetailsTest {
private static final int UID = 0;
private static final String PACKAGE_NAME = "com.android.fake.package";
@Mock
private AppOpsManager mAppOpsManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void isTurnScreenOnAllowed_appOpErrored_shouldReturnFalse() {
when(mAppOpsManager.checkOpNoThrow(eq(OP_TURN_SCREEN_ON), eq(UID),
eq(PACKAGE_NAME))).thenReturn(MODE_ERRORED);
boolean isAllowed = TurnScreenOnDetails.isTurnScreenOnAllowed(mAppOpsManager, UID,
PACKAGE_NAME);
assertThat(isAllowed).isFalse();
}
@Test
public void isTurnScreenOnAllowed_appOpAllowed_shouldReturnTrue() {
when(mAppOpsManager.checkOpNoThrow(eq(OP_TURN_SCREEN_ON), eq(UID),
eq(PACKAGE_NAME))).thenReturn(MODE_ALLOWED);
boolean isAllowed = TurnScreenOnDetails.isTurnScreenOnAllowed(mAppOpsManager, UID,
PACKAGE_NAME);
assertThat(isAllowed).isTrue();
}
}

View File

@@ -1,188 +0,0 @@
/*
* Copyright (C) 2022 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.turnscreenon;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.UserManager;
import android.util.Pair;
import com.android.settings.testutils.FakeFeatureFactory;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class TurnScreenOnSettingsTest {
private static final int PRIMARY_USER_ID = 0;
private static final int PROFILE_USER_ID = 10;
private TurnScreenOnSettings mFragment;
@Mock
private PackageManager mPackageManager;
@Mock
private UserManager mUserManager;
private ArrayList<PackageInfo> mPrimaryUserPackages;
private ArrayList<PackageInfo> mProfileUserPackages;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
mFragment = new TurnScreenOnSettings(mPackageManager, mUserManager);
mPrimaryUserPackages = new ArrayList<>();
mProfileUserPackages = new ArrayList<>();
when(mPackageManager.getInstalledPackagesAsUser(anyInt(), eq(PRIMARY_USER_ID)))
.thenReturn(mPrimaryUserPackages);
when(mPackageManager.getInstalledPackagesAsUser(anyInt(), eq(PROFILE_USER_ID)))
.thenReturn(mProfileUserPackages);
UserInfo primaryUserInfo = new UserInfo();
primaryUserInfo.id = PRIMARY_USER_ID;
UserInfo profileUserInfo = new UserInfo();
profileUserInfo.id = PROFILE_USER_ID;
when(mUserManager.getProfiles(PRIMARY_USER_ID))
.thenReturn(ImmutableList.of(primaryUserInfo, profileUserInfo));
}
@Test
public void testCollectTurnScreenOnApps_variousPackages_shouldReturnOnlyPackagesWithTurnScreenOnPermission() {
PackageInfo primaryP1 = createPackage("Calculator", true);
PackageInfo primaryP2 = createPackage("Clock", false);
PackageInfo profileP1 = createPackage("Browser", false);
PackageInfo profileP2 = createPackage("Files", true);
mPrimaryUserPackages.add(primaryP1);
mPrimaryUserPackages.add(primaryP2);
mProfileUserPackages.add(profileP1);
mProfileUserPackages.add(profileP2);
List<Pair<ApplicationInfo, Integer>> apps = mFragment.collectTurnScreenOnApps(
PRIMARY_USER_ID);
assertThat(containsPackages(apps, primaryP1, profileP2)).isTrue();
assertThat(containsPackages(apps, primaryP2, profileP1)).isFalse();
}
@Test
public void collectTurnScreenOnApps_noTurnScreenOnPackages_shouldReturnEmptyList() {
PackageInfo primaryP1 = createPackage("Calculator", false);
PackageInfo profileP1 = createPackage("Browser", false);
mPrimaryUserPackages.add(primaryP1);
mProfileUserPackages.add(profileP1);
List<Pair<ApplicationInfo, Integer>> apps = mFragment.collectTurnScreenOnApps(
PRIMARY_USER_ID);
assertThat(apps).isEmpty();
}
@Test
public void sort_multiplePackages_appsShouldBeOrderedByAppName() {
PackageInfo primaryP1 = createPackage("Android", true);
PackageInfo primaryP2 = createPackage("Boop", true);
PackageInfo primaryP3 = createPackage("Deck", true);
PackageInfo profileP1 = createPackage("Android", true);
PackageInfo profileP2 = createPackage("Cool", true);
PackageInfo profileP3 = createPackage("Fast", false);
mPrimaryUserPackages.add(primaryP1);
mPrimaryUserPackages.add(primaryP2);
mPrimaryUserPackages.add(primaryP3);
mProfileUserPackages.add(profileP1);
mProfileUserPackages.add(profileP2);
mProfileUserPackages.add(profileP3);
List<Pair<ApplicationInfo, Integer>> apps = mFragment.collectTurnScreenOnApps(
PRIMARY_USER_ID);
apps.sort(new TurnScreenOnSettings.AppComparator(null));
assertThat(isOrdered(apps, primaryP1, profileP1, primaryP2, profileP2, primaryP3)).isTrue();
}
@Test
public void hasTurnScreenOnPermission_ignoredPackages_shouldReturnFalse() {
boolean res = false;
for (String ignoredPackage : TurnScreenOnSettings.IGNORE_PACKAGE_LIST) {
res |= TurnScreenOnSettings.hasTurnScreenOnPermission(mPackageManager, ignoredPackage);
}
assertThat(res).isFalse();
}
private boolean containsPackages(List<Pair<ApplicationInfo, Integer>> apps,
PackageInfo... packages) {
for (PackageInfo aPackage : packages) {
boolean found = false;
for (Pair<ApplicationInfo, Integer> app : apps) {
if (app.first == aPackage.applicationInfo) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
private boolean isOrdered(List<Pair<ApplicationInfo, Integer>> apps, PackageInfo... packages) {
if (apps.size() != packages.length) {
return false;
}
for (int i = 0; i < packages.length; i++) {
if (packages[i].applicationInfo != apps.get(i).first) {
return false;
}
}
return true;
}
private PackageInfo createPackage(String packageName, boolean hasTurnScreenOnPermission) {
PackageInfo pi = new PackageInfo();
when(mPackageManager.checkPermission(Manifest.permission.TURN_SCREEN_ON,
packageName)).thenReturn(
hasTurnScreenOnPermission ? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED);
pi.packageName = packageName;
pi.applicationInfo = new ApplicationInfo();
pi.applicationInfo.name = packageName;
return pi;
}
}

View File

@@ -16,8 +16,8 @@
package com.android.settings.development;
import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.DEFAULT_REFRESH_RATE;
import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.NO_CONFIG;
import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
@@ -38,8 +38,6 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import android.util.Log;
@RunWith(RobolectricTestRunner.class)
public class ForcePeakRefreshRatePreferenceControllerTest {
@@ -63,22 +61,18 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
@Test
public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak() {
mController.mPeakRefreshRate = 88f;
mController.onPreferenceChange(mPreference, true);
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(88f);
assertThat(Settings.System.getInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, -1)).isEqualTo(1);
}
@Test
public void onPreferenceChange_preferenceUnchecked_shouldDisableForcePeak() {
mController.mPeakRefreshRate = 88f;
mController.onPreferenceChange(mPreference, false);
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(NO_CONFIG);
assertThat(Settings.System.getInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, -1)).isEqualTo(0);
}
@Test
@@ -125,8 +119,8 @@ public class ForcePeakRefreshRatePreferenceControllerTest {
public void onDeveloperOptionsDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsSwitchDisabled();
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.MIN_REFRESH_RATE, -1f)).isEqualTo(NO_CONFIG);
assertThat(Settings.System.getInt(mContext.getContentResolver(),
Settings.System.FORCE_PEAK_REFRESH_RATE, -1)).isEqualTo(0);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}

View File

@@ -16,15 +16,14 @@
package com.android.settings.display;
import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.android.settings.display.PeakRefreshRatePreferenceController.DEFAULT_REFRESH_RATE;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import android.view.Display;
import androidx.preference.SwitchPreference;
@@ -70,23 +69,21 @@ public class PeakRefreshRatePreferenceControllerTest {
}
@Test
public void setChecked_enableSmoothDisplay_setCurrentRefreshRate() {
mController.mPeakRefreshRate = 88f;
public void setChecked_enableSmoothDisplay() {
mController.setChecked(true);
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE, DEFAULT_REFRESH_RATE))
.isEqualTo(88.0f);
assertThat(Settings.System.getInt(mContext.getContentResolver(),
Settings.System.SMOOTH_DISPLAY, -1))
.isEqualTo(1);
}
@Test
public void setChecked_disableSmoothDisplay_setDefaultRefreshRate() {
mController.mPeakRefreshRate = 88f;
public void setChecked_disableSmoothDisplay() {
mController.setChecked(false);
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE, DEFAULT_REFRESH_RATE))
.isEqualTo(DEFAULT_REFRESH_RATE);
assertThat(Settings.System.getInt(mContext.getContentResolver(),
Settings.System.SMOOTH_DISPLAY, -1))
.isEqualTo(0);
}
@Test
@@ -103,36 +100,21 @@ public class PeakRefreshRatePreferenceControllerTest {
assertThat(mController.isChecked()).isFalse();
}
@Test
public void findPeakRefreshRate_moreThanOneHigherThanDefault() {
Display.Mode lower = new Display.Mode(0, 0, 0, DEFAULT_REFRESH_RATE - 1);
Display.Mode def = new Display.Mode(0, 0, 0, DEFAULT_REFRESH_RATE);
Display.Mode higher = new Display.Mode(0, 0, 0, DEFAULT_REFRESH_RATE + 1);
Display.Mode higher1 = new Display.Mode(0, 0, 0, DEFAULT_REFRESH_RATE + 2);
assertThat(mController.findPeakRefreshRate(
new Display.Mode[] {lower, def, higher, higher1}))
.isEqualTo(DEFAULT_REFRESH_RATE + 2);
assertThat(mController.findPeakRefreshRate(
new Display.Mode[] {lower, def, higher1, higher}))
.isEqualTo(DEFAULT_REFRESH_RATE + 2);
}
private void enableSmoothDisplayPreference() {
mController.mPeakRefreshRate = 88f;
Settings.System.putFloat(
Settings.System.putInt(
mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE,
mController.mPeakRefreshRate);
Settings.System.SMOOTH_DISPLAY,
1);
}
private void disableSmoothDisplayPreference() {
mController.mPeakRefreshRate = 88f;
Settings.System.putFloat(
Settings.System.putInt(
mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE,
DEFAULT_REFRESH_RATE);
Settings.System.SMOOTH_DISPLAY,
0);
}
}

View File

@@ -332,7 +332,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = 2;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
"10AM - 12PM");
"10 AM - 12 PM");
}
@Test
@@ -342,7 +342,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = 8;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
"Sunday 4PM - 6PM");
"Sunday 4 PM - 6 PM");
}
@Test
@@ -352,7 +352,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
"7:01AM - 8AM");
"7:01 AM - 8 AM");
}
@Test
@@ -362,7 +362,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = 3;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
"12PM - now");
"12 PM - now");
}
@Test
@@ -372,7 +372,7 @@ public final class BatteryChartPreferenceControllerTest {
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
"7:01AM - now");
"7:01 AM - now");
}
@Test

View File

@@ -23,6 +23,7 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_MEDIA_MANAGEMENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_RECENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_TURN_SCREEN_ON;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_USAGE_ACCESS;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WITH_OVERLAY;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WRITE_SETTINGS;
@@ -38,6 +39,7 @@ import static com.android.settings.applications.manageapplications.ManageApplica
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_OVERLAY;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_STORAGE;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_TURN_SCREEN_ON;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_USAGE_ACCESS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WRITE_SETTINGS;
@@ -82,5 +84,8 @@ public class AppFilterRegistryTest {
assertThat(registry.getDefaultFilterType(LIST_TYPE_LONG_BACKGROUND_TASKS))
.isEqualTo(FILTER_LONG_BACKGROUND_TASKS);
assertThat(registry.getDefaultFilterType(LIST_TYPE_TURN_SCREEN_ON)).isEqualTo(
FILTER_APPS_TURN_SCREEN_ON);
}
}