Add special app access for turning on the screen.

Bug: 216114297
Test: manually built and installed on device, verified absence of jank.
Test: atest SettingsRoboTests:TurnScreenOnDetailsTest
Test: atest SettingsRoboTests:TurnScreenOnSettingsTest
Change-Id: I1ed5948504222b537207978cbaa117b48aa28e6c
This commit is contained in:
Philip Junker
2022-03-14 18:08:46 +00:00
parent 8b096f0400
commit 8a9780527e
10 changed files with 675 additions and 1 deletions

View File

@@ -3117,6 +3117,24 @@
android:value="@string/menu_key_apps"/> android:value="@string/menu_key_apps"/>
</activity> </activity>
<activity
android:name="Settings$TurnScreenOnSettingsActivity"
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" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<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" />
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity>
<activity <activity
android:name="Settings$InteractAcrossProfilesSettingsActivity" android:name="Settings$InteractAcrossProfilesSettingsActivity"
android:exported="true" android:exported="true"

View File

@@ -156,6 +156,11 @@
android:value="com.android.settings.Settings$ChangeWifiStateActivity" /> android:value="com.android.settings.Settings$ChangeWifiStateActivity" />
</Preference> </Preference>
<Preference
android:key="turn_screen_on"
android:title="@string/turn_screen_on_title"
android:fragment="com.android.settings.applications.specialaccess.turnscreenon.TurnScreenOnSettings" />
<Preference <Preference
android:key="special_access_more" android:key="special_access_more"
android:title="@string/special_access_more" android:title="@string/special_access_more"

View File

@@ -0,0 +1,29 @@
<?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"
android:key="turn_screen_on_permission_detail_settings"
android:title="@string/turn_screen_on_title">
<com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch"
android:title="@string/allow_turn_screen_on"/>
<com.android.settingslib.widget.FooterPreference
android:title="@string/allow_turn_screen_on_description"
android:selectable="false"/>
</PreferenceScreen>

View File

@@ -0,0 +1,23 @@
<?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

@@ -271,6 +271,7 @@ public class Settings extends SettingsActivity {
public static class VrListenersSettingsActivity extends SettingsActivity { /* empty */ } public static class VrListenersSettingsActivity extends SettingsActivity { /* empty */ }
public static class PremiumSmsAccessActivity extends SettingsActivity { /* empty */ } public static class PremiumSmsAccessActivity extends SettingsActivity { /* empty */ }
public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ } public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
public static class TurnScreenOnSettingsActivity extends SettingsActivity { /* empty */ }
public static class AppPictureInPictureSettingsActivity extends SettingsActivity { /* empty */ } public static class AppPictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ } public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenAccessDetailSettingsActivity extends SettingsActivity {} public static class ZenAccessDetailSettingsActivity extends SettingsActivity {}

View File

@@ -0,0 +1,118 @@
/*
* 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 android.app.AppOpsManager;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
/**
* Detail page for turn screen on special app access.
*/
public class TurnScreenOnDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private SwitchPreference mSwitchPref;
private AppOpsManager mAppOpsManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppOpsManager = this.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) {
if (preference == mSwitchPref) {
setTurnScreenOnAppOp(mPackageInfo.applicationInfo.uid, mPackageName,
(Boolean) newValue);
return true;
}
return false;
}
@Override
protected boolean refreshUi() {
boolean isAllowed = isTurnScreenOnAllowed(mAppOpsManager,
mPackageInfo.applicationInfo.uid, mPackageName);
mSwitchPref.setChecked(isAllowed);
return true;
}
@Override
protected AlertDialog createDialog(int id, int errorCode) {
return null;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_MANAGE_TURN_SCREEN_ON;
}
/**
* 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;
}
/**
* @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
: R.string.app_permission_summary_not_allowed;
}
}

View File

@@ -0,0 +1,214 @@
/*
* 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.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("com.android.systemui");
}
/**
* 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_MANAGE_TURN_SCREEN_ON;
}
/**
* @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.WAKE_LOCK, packageName)
== PackageManager.PERMISSION_GRANTED;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.turn_screen_on_settings);
}

View File

@@ -60,6 +60,8 @@ import com.android.settings.applications.specialaccess.notificationaccess.Notifi
import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails; import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails;
import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings; import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings;
import com.android.settings.applications.specialaccess.premiumsms.PremiumSmsAccess; 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.vrlistener.VrListenerSettings;
import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails; import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
import com.android.settings.backup.PrivacySettings; import com.android.settings.backup.PrivacySettings;
@@ -335,7 +337,9 @@ public class SettingsGateway {
AutoBrightnessSettings.class.getName(), AutoBrightnessSettings.class.getName(),
OneHandedSettings.class.getName(), OneHandedSettings.class.getName(),
MobileNetworkSettings.class.getName(), MobileNetworkSettings.class.getName(),
AppLocaleDetails.class.getName() AppLocaleDetails.class.getName(),
TurnScreenOnSettings.class.getName(),
TurnScreenOnDetails.class.getName()
}; };
public static final String[] SETTINGS_FOR_RESTRICTED = { public static final String[] SETTINGS_FOR_RESTRICTED = {

View File

@@ -0,0 +1,74 @@
/*
* 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

@@ -0,0 +1,188 @@
/*
* 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.WAKE_LOCK,
packageName)).thenReturn(
hasTurnScreenOnPermission ? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED);
pi.packageName = packageName;
pi.applicationInfo = new ApplicationInfo();
pi.applicationInfo.name = packageName;
return pi;
}
}