diff --git a/res/drawable/homepage_app_bar_background.xml b/res/drawable/homepage_app_bar_background.xml
new file mode 100644
index 00000000000..6872ab77a6f
--- /dev/null
+++ b/res/drawable/homepage_app_bar_background.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/search_bar_two_pane_version.xml b/res/layout/search_bar_two_pane_version.xml
index ede57226699..9ce220c8c5f 100644
--- a/res/layout/search_bar_two_pane_version.xml
+++ b/res/layout/search_bar_two_pane_version.xml
@@ -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">
+ 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">
-
+
-
+
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 3de5a8a2dc4..89d40d08b44 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -34,6 +34,11 @@
android:layout_height="wrap_content"
android:orientation="vertical">
+
+
+
+
+
+
+
+
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3d616a83f74..b88d01d12b9 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -152,6 +152,12 @@
8dp
16dp
24dp
+ 32dp
+ 6dp
+
+ 10dp
+
+ 18dp
16dp
diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java
index 914c4b214d1..824a5a05dc1 100644
--- a/src/com/android/settings/DefaultRingtonePreference.java
+++ b/src/com/android/settings/DefaultRingtonePreference.java
@@ -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
diff --git a/src/com/android/settings/applications/AppStateBaseBridge.java b/src/com/android/settings/applications/AppStateBaseBridge.java
index d7f253b6c0b..a4bdabf43e3 100644
--- a/src/com/android/settings/applications/AppStateBaseBridge.java
+++ b/src/com/android/settings/applications/AppStateBaseBridge.java
@@ -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 {
diff --git a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
index 9cb5a3f851a..708f8b7004d 100644
--- a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
+++ b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
@@ -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();
diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
index f5e21ddc1b2..9860240b289 100644
--- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
+++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
@@ -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 mTestApplicationInfoList = null;
+ ArraySet mTestApplicationInfoList = null;
@VisibleForTesting
PowerAllowlistBackend mPowerAllowlistBackend;
@@ -146,7 +134,7 @@ public final class BatteryBackupHelper implements BackupHelper {
@VisibleForTesting
void backupOptimizationMode(BackupDataOutput data, List allowlistedApps) {
final long timestamp = System.currentTimeMillis();
- final List applications = getInstalledApplications();
+ final ArraySet 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 getInstalledApplications() {
+ private ArraySet getInstalledApplications() {
if (mTestApplicationInfoList != null) {
return mTestApplicationInfoList;
}
- final List applications = new ArrayList<>();
- final UserManager um = mContext.getSystemService(UserManager.class);
- for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
- try {
- @SuppressWarnings("unchecked")
- final ParceledListSlice 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) {
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index 9306a34df67..dbfacc6907c 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -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 getInstalledApplications(
+ Context context, IPackageManager ipm) {
+ final ArraySet applications = new ArraySet<>();
+ final UserManager um = context.getSystemService(UserManager.class);
+ for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
+ try {
+ @SuppressWarnings("unchecked")
+ final ParceledListSlice 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 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));
}
}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 86b123be49b..c7bd3b5712e 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -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 {
diff --git a/src/com/android/settings/wfd/WifiDisplayPreferenceController.java b/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
index a83a56b5945..b15396b7ed2 100644
--- a/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
+++ b/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
@@ -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;
}
}
diff --git a/src/com/android/settings/wfd/WifiDisplaySettings.java b/src/com/android/settings/wfd/WifiDisplaySettings.java
index 19b6c5457d7..8562e5fd68b 100755
--- a/src/com/android/settings/wfd/WifiDisplaySettings.java
+++ b/src/com/android/settings/wfd/WifiDisplaySettings.java
@@ -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()) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index ca1797ac9e9..14bbeea7187 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -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(
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)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
index c154f426b30..b223d0bc755 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
@@ -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(
+ Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3, applicationInfo4)))
+ .when(mMockIPackageManager)
+ .getInstalledApplications(anyLong(), anyInt());
+
+ final ArraySet 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(
+ 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);
+ }
+ }
}