Snap for 8597652 from 2a4097b074 to udc-release

Change-Id: I87a2f1bb66f934523e29695acede39993ca7a01a
This commit is contained in:
Android Build Coastguard Worker
2022-05-17 03:09:33 +00:00
16 changed files with 409 additions and 117 deletions

View File

@@ -0,0 +1,24 @@
<?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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="@color/settings_two_pane_background_color" />
<corners
android:bottomLeftRadius="@dimen/homepage_app_bar_corner_radius"
android:bottomRightRadius="@dimen/homepage_app_bar_corner_radius" />
</shape>

View File

@@ -21,8 +21,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="@dimen/search_bar_margin"
android:layout_marginVertical="@dimen/search_bar_margin">
android:layout_marginEnd="@dimen/search_bar_margin">
<Toolbar
android:id="@+id/search_action_bar_two_pane"
android:layout_width="match_parent"

View File

@@ -17,29 +17,21 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/app_bar_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/settings_two_pane_background_color">
android:layout_marginHorizontal="@dimen/homepage_app_bar_margin_horizontal_two_pane"
android:padding="@dimen/homepage_app_bar_padding_two_pane"
android:orientation="horizontal"
android:background="@drawable/homepage_app_bar_background">
<FrameLayout
android:id="@+id/two_pane_suggestion_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include layout="@layout/search_bar_two_pane_version"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/account_avatar_two_pane_version"
android:layout_width="@dimen/avatar_length"
android:layout_height="@dimen/avatar_length"
android:layout_gravity="center"
android:contentDescription="@string/search_bar_account_avatar_content_description"/>
<include layout="@layout/search_bar_two_pane_version"/>
<ImageView
android:id="@+id/account_avatar_two_pane_version"
android:layout_width="@dimen/avatar_length"
android:layout_height="@dimen/avatar_length"
android:layout_gravity="center"
android:contentDescription="@string/search_bar_account_avatar_content_description"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -34,6 +34,11 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/suggestion_container_two_pane"
layout="@layout/suggestion_container_two_pane"
android:visibility="gone"/>
<FrameLayout
android:id="@+id/contextual_cards_content"
android:layout_width="match_parent"

View File

@@ -0,0 +1,30 @@
<?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.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/homepage_app_bar_margin_bottom_two_pane"
android:layout_marginHorizontal="@dimen/homepage_padding_horizontal_two_pane">
<FrameLayout
android:id="@+id/two_pane_suggestion_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>

View File

@@ -152,6 +152,12 @@
<dimen name="homepage_preference_icon_padding_start_two_pane">8dp</dimen>
<dimen name="homepage_preference_text_padding_start">16dp</dimen>
<dimen name="homepage_preference_text_padding_start_two_pane">24dp</dimen>
<dimen name="homepage_app_bar_corner_radius">32dp</dimen>
<dimen name="homepage_app_bar_padding_two_pane">6dp</dimen>
<!-- bottom: search_bar_margin - homepage_app_bar_padding_two_pane -->
<dimen name="homepage_app_bar_margin_bottom_two_pane">10dp</dimen>
<!-- horizontal: homepage_padding_horizontal_two_pane - homepage_app_bar_padding_two_pane -->
<dimen name="homepage_app_bar_margin_horizontal_two_pane">18dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>

View File

@@ -46,6 +46,11 @@ public class DefaultRingtonePreference extends RingtonePreference {
@Override
protected void onSaveRingtone(Uri ringtoneUri) {
if (ringtoneUri == null) {
setActualDefaultRingtoneUri(ringtoneUri);
return;
}
String mimeType = getContext().getContentResolver().getType(ringtoneUri);
if (mimeType == null) {
Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri

View File

@@ -52,7 +52,6 @@ public abstract class AppStateBaseBridge implements ApplicationsState.Callbacks
public void resume(boolean forceLoadAllApps) {
mForceLoadAllApps = forceLoadAllApps;
mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
if (mForceLoadAllApps) {
mAppSession.onResume();
} else {

View File

@@ -38,6 +38,7 @@ import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryOptimizeUtils;
import java.util.Arrays;
import java.util.List;
@@ -152,6 +153,7 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener,
} catch (RemoteException e) {
}
mAom.resetAllModes();
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
final int[] restrictedUids = mNpm.getUidsWithPolicy(
POLICY_REJECT_METERED_BACKGROUND);
final int currentUserId = ActivityManager.getCurrentUser();

View File

@@ -24,16 +24,13 @@ import android.app.backup.BackupHelper;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.IDeviceIdleController;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -53,22 +50,13 @@ public final class BatteryBackupHelper implements BackupHelper {
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
private static final boolean DEBUG = Build.TYPE.equals("userdebug");
// Only the owner can see all apps.
private static final int RETRIEVE_FLAG_ADMIN =
PackageManager.MATCH_ANY_USER |
PackageManager.MATCH_DISABLED_COMPONENTS |
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
private static final int RETRIEVE_FLAG =
PackageManager.MATCH_DISABLED_COMPONENTS |
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
static final String DELIMITER = ",";
static final String DELIMITER_MODE = ":";
static final String KEY_FULL_POWER_LIST = "full_power_list";
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
@VisibleForTesting
List<ApplicationInfo> mTestApplicationInfoList = null;
ArraySet<ApplicationInfo> mTestApplicationInfoList = null;
@VisibleForTesting
PowerAllowlistBackend mPowerAllowlistBackend;
@@ -146,7 +134,7 @@ public final class BatteryBackupHelper implements BackupHelper {
@VisibleForTesting
void backupOptimizationMode(BackupDataOutput data, List<String> allowlistedApps) {
final long timestamp = System.currentTimeMillis();
final List<ApplicationInfo> applications = getInstalledApplications();
final ArraySet<ApplicationInfo> applications = getInstalledApplications();
if (applications == null || applications.isEmpty()) {
Log.w(TAG, "no data found in the getInstalledApplications()");
return;
@@ -269,36 +257,11 @@ public final class BatteryBackupHelper implements BackupHelper {
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
}
private List<ApplicationInfo> getInstalledApplications() {
private ArraySet<ApplicationInfo> getInstalledApplications() {
if (mTestApplicationInfoList != null) {
return mTestApplicationInfoList;
}
final List<ApplicationInfo> applications = new ArrayList<>();
final UserManager um = mContext.getSystemService(UserManager.class);
for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
try {
@SuppressWarnings("unchecked")
final ParceledListSlice<ApplicationInfo> infoList =
getIPackageManager().getInstalledApplications(
userInfo.isAdmin() ? RETRIEVE_FLAG_ADMIN : RETRIEVE_FLAG,
userInfo.id);
if (infoList != null) {
applications.addAll(infoList.getList());
}
} catch (Exception e) {
Log.e(TAG, "getInstalledApplications() is failed", e);
return null;
}
}
// Removes the application which is disabled by the system.
for (int index = applications.size() - 1; index >= 0; index--) {
final ApplicationInfo info = applications.get(index);
if (info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
&& !info.enabled) {
applications.remove(index);
}
}
return applications;
return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager());
}
private void debugLog(String debugContent) {

View File

@@ -19,7 +19,15 @@ package com.android.settings.fuelgauge;
import android.annotation.IntDef;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.os.AsyncTask;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -43,6 +51,15 @@ public class BatteryOptimizeUtils {
private final String mPackageName;
private final int mUid;
// If current user is admin, match apps from all users. Otherwise, only match the currect user.
private static final int RETRIEVE_FLAG_ADMIN =
PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
private static final int RETRIEVE_FLAG =
PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
// Optimization modes.
static final int MODE_UNKNOWN = 0;
static final int MODE_RESTRICTED = 1;
@@ -90,28 +107,20 @@ public class BatteryOptimizeUtils {
return getAppOptimizationMode(mMode, mAllowListed);
}
/** Resets optimization mode for all applications. */
public static void resetAppOptimizationMode(
Context context, IPackageManager ipm, AppOpsManager aom) {
resetAppOptimizationMode(context, ipm, aom,
PowerAllowlistBackend.getInstance(context), BatteryUtils.getInstance(context));
}
/** Sets the {@link OptimizationMode} for associated app. */
public void setAppUsageState(@OptimizationMode int mode) {
if (getAppOptimizationMode(mMode, mAllowListed) == mode) {
Log.w(TAG, "set the same optimization mode for: " + mPackageName);
return;
}
AsyncTask.execute(() -> {
switch (mode) {
case MODE_RESTRICTED:
setAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
break;
case MODE_UNRESTRICTED:
setAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
break;
case MODE_OPTIMIZED:
setAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
break;
default:
Log.d(TAG, "set unknown app optimization mode.");
}
});
setAppUsageStateInternal(mode, mUid, mPackageName, mBatteryUtils, mPowerAllowListBackend);
}
/**
@@ -126,25 +135,111 @@ public class BatteryOptimizeUtils {
*/
public boolean isSystemOrDefaultApp() {
mPowerAllowListBackend.refreshList();
return isSystemOrDefaultApp(mPowerAllowListBackend, mPackageName);
}
return mPowerAllowListBackend.isSysAllowlisted(mPackageName)
|| mPowerAllowListBackend.isDefaultActiveApp(mPackageName);
/**
* Gets the list of installed applications.
*/
public static ArraySet<ApplicationInfo> getInstalledApplications(
Context context, IPackageManager ipm) {
final ArraySet<ApplicationInfo> applications = new ArraySet<>();
final UserManager um = context.getSystemService(UserManager.class);
for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
try {
@SuppressWarnings("unchecked")
final ParceledListSlice<ApplicationInfo> infoList = ipm.getInstalledApplications(
userInfo.isAdmin() ? RETRIEVE_FLAG_ADMIN : RETRIEVE_FLAG,
userInfo.id);
if (infoList != null) {
applications.addAll(infoList.getList());
}
} catch (Exception e) {
Log.e(TAG, "getInstalledApplications() is failed", e);
return null;
}
}
// Removes the application which is disabled by the system.
applications.removeIf(
info -> info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
&& !info.enabled);
return applications;
}
@VisibleForTesting
static void resetAppOptimizationMode(
Context context, IPackageManager ipm, AppOpsManager aom,
PowerAllowlistBackend allowlistBackend, BatteryUtils batteryUtils) {
final ArraySet<ApplicationInfo> applications = getInstalledApplications(context, ipm);
if (applications == null || applications.isEmpty()) {
Log.w(TAG, "no data found in the getInstalledApplications()");
return;
}
allowlistBackend.refreshList();
// Resets optimization mode for each application.
for (ApplicationInfo info : applications) {
final int mode = aom.checkOpNoThrow(
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, info.uid, info.packageName);
@OptimizationMode
final int optimizationMode = getAppOptimizationMode(
mode, allowlistBackend.isAllowlisted(info.packageName));
// Ignores default optimized/unknown state or system/default apps.
if (optimizationMode == MODE_OPTIMIZED
|| optimizationMode == MODE_UNKNOWN
|| isSystemOrDefaultApp(allowlistBackend, info.packageName)) {
continue;
}
// Resets to the default mode: MODE_OPTIMIZED.
setAppUsageStateInternal(MODE_OPTIMIZED, info.uid, info.packageName, batteryUtils,
allowlistBackend);
}
}
String getPackageName() {
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
}
private void setAppOptimizationMode(int appStandbyMode, boolean allowListed) {
private static boolean isSystemOrDefaultApp(
PowerAllowlistBackend powerAllowlistBackend, String packageName) {
return powerAllowlistBackend.isSysAllowlisted(packageName)
|| powerAllowlistBackend.isDefaultActiveApp(packageName);
}
private static void setAppUsageStateInternal(
@OptimizationMode int mode, int uid, String packageName, BatteryUtils batteryUtils,
PowerAllowlistBackend powerAllowlistBackend) {
if (mode == MODE_UNKNOWN) {
Log.d(TAG, "set unknown app optimization mode.");
return;
}
// MODE_RESTRICTED = AppOpsManager.MODE_IGNORED + !allowListed
// MODE_UNRESTRICTED = AppOpsManager.MODE_ALLOWED + allowListed
// MODE_OPTIMIZED = AppOpsManager.MODE_ALLOWED + !allowListed
final int appOpsManagerMode =
mode == MODE_RESTRICTED ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED;
final boolean allowListed = mode == MODE_UNRESTRICTED;
AsyncTask.execute(() -> {
setAppOptimizationModeInternal(appOpsManagerMode, allowListed, uid, packageName,
batteryUtils, powerAllowlistBackend);
});
}
private static void setAppOptimizationModeInternal(
int appStandbyMode, boolean allowListed, int uid, String packageName,
BatteryUtils batteryUtils, PowerAllowlistBackend powerAllowlistBackend) {
try {
mBatteryUtils.setForceAppStandby(mUid, mPackageName, appStandbyMode);
batteryUtils.setForceAppStandby(uid, packageName, appStandbyMode);
if (allowListed) {
mPowerAllowListBackend.addApp(mPackageName);
powerAllowlistBackend.addApp(packageName);
} else {
mPowerAllowListBackend.removeApp(mPackageName);
powerAllowlistBackend.removeApp(packageName);
}
} catch (Exception e) {
Log.e(TAG, "set OPTIMIZED failed for " + mPackageName, e);
Log.e(TAG, "set OPTIMIZATION MODE failed for " + packageName, e);
}
}
@@ -154,8 +249,6 @@ public class BatteryOptimizeUtils {
mMode = mAppOpsManager
.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d",
mPackageName,
mAllowListed,
mMode));
mPackageName, mAllowListed, mMode));
}
}

View File

@@ -89,7 +89,6 @@ public class SettingsHomepageActivity extends FragmentActivity implements
private TopLevelSettings mMainFragment;
private View mHomepageView;
private View mAppBar;
private View mSuggestionView;
private View mTwoPaneSuggestionView;
private CategoryMixin mCategoryMixin;
@@ -174,8 +173,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
mSplitController = SplitController.getInstance();
mIsTwoPane = mSplitController.isActivityEmbedded(this);
mAppBar = findViewById(R.id.app_bar_container);
mAppBar.setMinimumHeight(getSearchBoxHeight());
updateAppBarMinHeight();
initHomepageContainer();
updateHomepageAppBar();
updateHomepageBackground();
@@ -491,12 +489,15 @@ public class SettingsHomepageActivity extends FragmentActivity implements
if (!mIsEmbeddingActivityEnabled) {
return;
}
updateAppBarMinHeight();
if (mIsTwoPane) {
findViewById(R.id.homepage_app_bar_regular_phone_view).setVisibility(View.GONE);
findViewById(R.id.homepage_app_bar_two_pane_view).setVisibility(View.VISIBLE);
findViewById(R.id.suggestion_container_two_pane).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.homepage_app_bar_regular_phone_view).setVisibility(View.VISIBLE);
findViewById(R.id.homepage_app_bar_two_pane_view).setVisibility(View.GONE);
findViewById(R.id.suggestion_container_two_pane).setVisibility(View.GONE);
}
}
@@ -507,19 +508,20 @@ public class SettingsHomepageActivity extends FragmentActivity implements
if (mIsTwoPane) {
int padding = getResources().getDimensionPixelSize(
R.dimen.homepage_padding_horizontal_two_pane);
mAppBar.setPaddingRelative(padding, 0, padding, 0);
mMainFragment.setPaddingHorizontal(padding);
} else {
mAppBar.setPaddingRelative(0, 0, 0, 0);
mMainFragment.setPaddingHorizontal(0);
}
mMainFragment.updatePreferencePadding(mIsTwoPane);
}
private int getSearchBoxHeight() {
private void updateAppBarMinHeight() {
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin);
return searchBarHeight + searchBarMargin * 2;
final int margin = getResources().getDimensionPixelSize(
mIsEmbeddingActivityEnabled && mIsTwoPane
? R.dimen.homepage_app_bar_padding_two_pane
: R.dimen.search_bar_margin);
findViewById(R.id.app_bar_container).setMinimumHeight(searchBarHeight + margin * 2);
}
private static class SuggestionFragCreator implements FragmentCreator {

View File

@@ -19,6 +19,7 @@ package com.android.settings.wfd;
import android.content.Context;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -87,7 +88,12 @@ public class WifiDisplayPreferenceController extends BasePreferenceController im
final MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)
&& route.isSelected() && !route.isConnecting()) {
summary = mContext.getString(R.string.wifi_display_status_connected);
CharSequence status = route.getStatus();
if (!TextUtils.isEmpty(status)) {
summary = status;
} else {
summary = mContext.getString(R.string.wifi_display_status_connected);
}
break;
}
}

View File

@@ -38,6 +38,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
import android.util.TypedValue;
import android.view.Menu;
@@ -678,7 +679,12 @@ public final class WifiDisplaySettings extends SettingsPreferenceFragment implem
if (route.isConnecting()) {
setSummary(R.string.wifi_display_status_connecting);
} else {
setSummary(R.string.wifi_display_status_connected);
CharSequence status = route.getStatus();
if (!TextUtils.isEmpty(status)) {
setSummary(status);
} else {
setSummary(R.string.wifi_display_status_connected);
}
}
} else {
if (isEnabled()) {

View File

@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -48,6 +49,7 @@ import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
@@ -193,7 +195,7 @@ public final class BatteryBackupHelperTest {
doReturn(Arrays.asList(userInfo)).when(mUserManager).getProfiles(anyInt());
doThrow(new RuntimeException())
.when(mIPackageManager)
.getInstalledApplications(anyInt(), anyInt());
.getInstalledApplications(anyLong(), anyInt());
mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, null);
@@ -369,7 +371,7 @@ public final class BatteryBackupHelperTest {
doReturn(new ParceledListSlice<ApplicationInfo>(
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3)))
.when(mIPackageManager)
.getInstalledApplications(anyInt(), anyInt());
.getInstalledApplications(anyLong(), anyInt());
// Sets the AppOpsManager for checkOpNoThrow() method.
doReturn(AppOpsManager.MODE_ALLOWED)
.when(mAppOpsManager)
@@ -384,7 +386,7 @@ public final class BatteryBackupHelperTest {
applicationInfo2.uid,
applicationInfo2.packageName);
mBatteryBackupHelper.mTestApplicationInfoList =
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3);
new ArraySet<>(Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3));
}
@Implements(UserHandle.class)

View File

@@ -22,26 +22,43 @@ import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRIC
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.os.UserManager;
import android.util.ArraySet;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
@@ -50,9 +67,11 @@ public class BatteryOptimizeUtilsTest {
private static final int UID = 12345;
private static final String PACKAGE_NAME = "com.android.app";
@Mock BatteryUtils mMockBatteryUtils;
@Mock AppOpsManager mMockAppOpsManager;
@Mock PowerAllowlistBackend mMockBackend;
@Mock private BatteryUtils mMockBatteryUtils;
@Mock private AppOpsManager mMockAppOpsManager;
@Mock private PowerAllowlistBackend mMockBackend;
@Mock private IPackageManager mMockIPackageManager;
@Mock private UserManager mMockUserManager;
private Context mContext;
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@@ -68,6 +87,7 @@ public class BatteryOptimizeUtilsTest {
// Sets the default mode as MODE_RESTRICTED.
mBatteryOptimizeUtils.mMode = AppOpsManager.MODE_IGNORED;
mBatteryOptimizeUtils.mAllowListed = false;
doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
}
@Test
@@ -135,9 +155,7 @@ public class BatteryOptimizeUtilsTest {
mBatteryOptimizeUtils.setAppUsageState(MODE_RESTRICTED);
TimeUnit.SECONDS.sleep(1);
verify(mMockBatteryUtils).setForceAppStandby(UID,
PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
verify(mMockBackend).removeApp(PACKAGE_NAME);
verifySetAppOptimizationMode(AppOpsManager.MODE_IGNORED, /* allowListed */ false);
}
@Test
@@ -145,9 +163,7 @@ public class BatteryOptimizeUtilsTest {
mBatteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED);
TimeUnit.SECONDS.sleep(1);
verify(mMockBatteryUtils).setForceAppStandby(UID,
PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
verify(mMockBackend).addApp(PACKAGE_NAME);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ true);
}
@Test
@@ -155,9 +171,7 @@ public class BatteryOptimizeUtilsTest {
mBatteryOptimizeUtils.setAppUsageState(MODE_OPTIMIZED);
TimeUnit.SECONDS.sleep(1);
verify(mMockBatteryUtils).setForceAppStandby(UID,
PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
verify(mMockBackend).removeApp(PACKAGE_NAME);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
@Test
@@ -172,4 +186,148 @@ public class BatteryOptimizeUtilsTest {
verifyZeroInteractions(mMockBackend);
verifyZeroInteractions(mMockBatteryUtils);
}
@Test
public void testGetInstalledApplications_returnEmptyArray() {
assertTrue(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager)
.isEmpty());
}
@Test
public void testGetInstalledApplications_returnNull() throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
doThrow(new RuntimeException())
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
assertNull(BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager));
}
@Test
public void testGetInstalledApplications_returnInstalledApps() throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
final ApplicationInfo applicationInfo1 = new ApplicationInfo();
applicationInfo1.enabled = true;
applicationInfo1.uid = 1;
final ApplicationInfo applicationInfo2 = new ApplicationInfo();
applicationInfo2.enabled = false;
applicationInfo2.uid = 2;
applicationInfo2.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
final ApplicationInfo applicationInfo3 = new ApplicationInfo();
applicationInfo3.enabled = false;
applicationInfo3.uid = 3;
applicationInfo3.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
final ApplicationInfo applicationInfo4 = new ApplicationInfo();
applicationInfo4.enabled = true;
applicationInfo4.uid = 4;
applicationInfo4.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
doReturn(new ParceledListSlice<ApplicationInfo>(
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3, applicationInfo4)))
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
final ArraySet<ApplicationInfo> applications =
BatteryOptimizeUtils.getInstalledApplications(mContext, mMockIPackageManager);
assertThat(applications.size()).isEqualTo(3);
// applicationInfo3 should be filtered.
assertTrue(applications.contains(applicationInfo1));
assertTrue(applications.contains(applicationInfo2));
assertFalse(applications.contains(applicationInfo3));
assertTrue(applications.contains(applicationInfo4));
}
@Test
public void testResetAppOptimizationMode_Optimized_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ false,
/* isSystemOrDefaultApp */ false);
verifyZeroInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
verifyNoMoreInteractions(mMockBackend);
}
@Test
public void testResetAppOptimizationMode_SystemOrDefault_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
/* isSystemOrDefaultApp */ true);
verifyZeroInteractions(mMockBatteryUtils);
final InOrder inOrder = inOrder(mMockBackend);
inOrder.verify(mMockBackend).refreshList();
inOrder.verify(mMockBackend).isAllowlisted(PACKAGE_NAME);
inOrder.verify(mMockBackend).isSysAllowlisted(PACKAGE_NAME);
verifyNoMoreInteractions(mMockBackend);
}
@Test
public void testResetAppOptimizationMode_Restricted_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_IGNORED, /* allowListed */ false,
/* isSystemOrDefaultApp */ false);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
@Test
public void testResetAppOptimizationMode_Unrestricted_verifyAction() throws Exception {
runTestForResetWithMode(
AppOpsManager.MODE_ALLOWED, /* allowListed */ true,
/* isSystemOrDefaultApp */ false);
verifySetAppOptimizationMode(AppOpsManager.MODE_ALLOWED, /* allowListed */ false);
}
private void runTestForResetWithMode(
int appStandbyMode, boolean allowListed, boolean isSystemOrDefaultApp)
throws Exception {
final UserInfo userInfo =
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
doReturn(Arrays.asList(userInfo)).when(mMockUserManager).getProfiles(anyInt());
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = UID;
applicationInfo.packageName = PACKAGE_NAME;
applicationInfo.enabled = true;
doReturn(new ParceledListSlice<ApplicationInfo>(
Arrays.asList(applicationInfo)))
.when(mMockIPackageManager)
.getInstalledApplications(anyLong(), anyInt());
doReturn(appStandbyMode)
.when(mMockAppOpsManager)
.checkOpNoThrow(anyInt(), anyInt(), anyString());
doReturn(allowListed)
.when(mMockBackend)
.isAllowlisted(anyString());
doReturn(isSystemOrDefaultApp)
.when(mMockBackend)
.isSysAllowlisted(anyString());
doReturn(isSystemOrDefaultApp)
.when(mMockBackend)
.isDefaultActiveApp(anyString());
BatteryOptimizeUtils.resetAppOptimizationMode(
mContext, mMockIPackageManager, mMockAppOpsManager, mMockBackend,
mMockBatteryUtils);
TimeUnit.SECONDS.sleep(1);
}
private void verifySetAppOptimizationMode(int appStandbyMode, boolean allowListed) {
verify(mMockBatteryUtils).setForceAppStandby(UID, PACKAGE_NAME, appStandbyMode);
if (allowListed) {
verify(mMockBackend).addApp(PACKAGE_NAME);
} else {
verify(mMockBackend).removeApp(PACKAGE_NAME);
}
}
}