Snap for 7666971 from a980758c5c to sc-v2-release
Change-Id: Iaa1e62c789183e232268ad8ed5c4262bf69dd935
This commit is contained in:
@@ -273,10 +273,6 @@
|
||||
<action android:name="android.settings.WIFI_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.android.settings.SHORTCUT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.wifi.WifiSettings" />
|
||||
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
|
||||
@@ -285,7 +281,7 @@
|
||||
|
||||
<activity
|
||||
android:name="Settings$NetworkProviderSettingsActivity"
|
||||
android:label="@string/network_dashboard_title"
|
||||
android:label="@string/provider_internet_settings"
|
||||
android:icon="@drawable/ic_homepage_network"
|
||||
android:exported="true"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
|
||||
@@ -13404,8 +13404,10 @@
|
||||
<string name="carrier_wifi_network_title">W+ network</string>
|
||||
<!-- Provider Model: title of SIM category -->
|
||||
<string name="sim_category_title">SIM</string>
|
||||
<!-- Provider Model: title of Downloaded category. [CHAR LIMIT=50] -->
|
||||
<!-- Provider Model: title of Downloaded SIM category. [CHAR LIMIT=50] -->
|
||||
<string name="downloaded_sim_category_title">DOWNLOADED SIM</string>
|
||||
<!-- Provider Model: title of Downloaded SIMs category. [CHAR LIMIT=50] -->
|
||||
<string name="downloaded_sims_category_title">DOWNLOADED SIMS</string>
|
||||
<!-- Provider Model: summary of Active in SIM category. [CHAR LIMIT=50] -->
|
||||
<string name="sim_category_active_sim">Active</string>
|
||||
<!-- Provider Model: summary of Inactive in SIM category. [CHAR LIMIT=50] -->
|
||||
|
||||
@@ -16,21 +16,33 @@
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.backup.BackupDataInputStream;
|
||||
import android.app.backup.BackupDataOutput;
|
||||
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.IDeviceIdleController;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/** An implementation to backup and restore battery configurations. */
|
||||
public final class BatteryBackupHelper implements BackupHelper {
|
||||
@@ -39,13 +51,24 @@ public final class BatteryBackupHelper implements BackupHelper {
|
||||
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@VisibleForTesting
|
||||
static final CharSequence DELIMITER = ":";
|
||||
@VisibleForTesting
|
||||
// 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 CharSequence DELIMITER = ",";
|
||||
static final CharSequence DELIMITER_MODE = "|";
|
||||
static final String KEY_FULL_POWER_LIST = "full_power_list";
|
||||
static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
|
||||
|
||||
@VisibleForTesting
|
||||
IDeviceIdleController mIDeviceIdleController;
|
||||
@VisibleForTesting
|
||||
IPackageManager mIPackageManager;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
@@ -57,10 +80,13 @@ public final class BatteryBackupHelper implements BackupHelper {
|
||||
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState) {
|
||||
if (!isOwner()) {
|
||||
Log.w(TAG, "ignore the backup process for non-owner");
|
||||
Log.w(TAG, "ignore performBackup() for non-owner");
|
||||
return;
|
||||
}
|
||||
backupFullPowerList(getIDeviceIdleController(), data);
|
||||
final List<String> allowlistedApps = backupFullPowerList(data);
|
||||
if (allowlistedApps != null) {
|
||||
backupOptimizationMode(data, allowlistedApps);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,33 +98,57 @@ public final class BatteryBackupHelper implements BackupHelper {
|
||||
public void writeNewStateDescription(ParcelFileDescriptor newState) {
|
||||
}
|
||||
|
||||
private void backupFullPowerList(
|
||||
IDeviceIdleController deviceIdleService, BackupDataOutput data) {
|
||||
private List<String> backupFullPowerList(BackupDataOutput data) {
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
String[] allowlistedApps;
|
||||
try {
|
||||
allowlistedApps = deviceIdleService.getFullPowerWhitelist();
|
||||
allowlistedApps = getIDeviceIdleController().getFullPowerWhitelist();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "backupFullPowerList() failed", e);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
// Ignores unexpected emptty result case.
|
||||
if (allowlistedApps == null || allowlistedApps.length == 0) {
|
||||
Log.w(TAG, "no data found in the getFullPowerList()");
|
||||
return;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
debugLog("allowlistedApps:" + Arrays.toString(allowlistedApps));
|
||||
final String allowedApps = String.join(DELIMITER, allowlistedApps);
|
||||
final byte[] allowedAppsBytes = allowedApps.getBytes();
|
||||
try {
|
||||
data.writeEntityHeader(KEY_FULL_POWER_LIST, allowedAppsBytes.length);
|
||||
data.writeEntityData(allowedAppsBytes, allowedAppsBytes.length);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "backup getFullPowerList() failed", e);
|
||||
return;
|
||||
}
|
||||
writeBackupData(data, KEY_FULL_POWER_LIST, allowedApps);
|
||||
Log.d(TAG, String.format("backup getFullPowerList() size=%d in %d/ms",
|
||||
allowlistedApps.length, (System.currentTimeMillis() - timestamp)));
|
||||
return Arrays.asList(allowlistedApps);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void backupOptimizationMode(BackupDataOutput data, List<String> allowlistedApps) {
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
final List<ApplicationInfo> applications = getInstalledApplications();
|
||||
if (applications == null || applications.isEmpty()) {
|
||||
Log.w(TAG, "no data found in the getInstalledApplications()");
|
||||
return;
|
||||
}
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
|
||||
// Converts application into the AppUsageState.
|
||||
for (ApplicationInfo info : applications) {
|
||||
final int mode = appOps.checkOpNoThrow(
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, info.uid, info.packageName);
|
||||
final AppUsageState state = BatteryOptimizeUtils.getAppUsageState(
|
||||
mode, allowlistedApps.contains(info.packageName));
|
||||
// Ignores default optimized or unknown state.
|
||||
if (state == AppUsageState.OPTIMIZED || state == AppUsageState.UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
final String packageOptimizeMode = info.packageName + DELIMITER_MODE + state;
|
||||
builder.append(packageOptimizeMode + DELIMITER);
|
||||
debugLog(packageOptimizeMode);
|
||||
}
|
||||
|
||||
writeBackupData(data, KEY_OPTIMIZATION_LIST, builder.toString());
|
||||
Log.d(TAG, String.format("backup getInstalledApplications() size=%d in %d/ms",
|
||||
applications.size(), (System.currentTimeMillis() - timestamp)));
|
||||
}
|
||||
|
||||
// Provides an opportunity to inject mock IDeviceIdleController for testing.
|
||||
@@ -111,10 +161,58 @@ public final class BatteryBackupHelper implements BackupHelper {
|
||||
return mIDeviceIdleController;
|
||||
}
|
||||
|
||||
private IPackageManager getIPackageManager() {
|
||||
if (mIPackageManager != null) {
|
||||
return mIPackageManager;
|
||||
}
|
||||
mIPackageManager = AppGlobals.getPackageManager();
|
||||
return mIPackageManager;
|
||||
}
|
||||
|
||||
private List<ApplicationInfo> getInstalledApplications() {
|
||||
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;
|
||||
}
|
||||
|
||||
private void debugLog(String debugContent) {
|
||||
if (DEBUG) Log.d(TAG, debugContent);
|
||||
}
|
||||
|
||||
private static void writeBackupData(
|
||||
BackupDataOutput data, String dataKey, String dataContent) {
|
||||
final byte[] dataContentBytes = dataContent.getBytes();
|
||||
try {
|
||||
data.writeEntityHeader(dataKey, dataContentBytes.length);
|
||||
data.writeEntityData(dataContentBytes, dataContentBytes.length);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "writeBackupData() is failed for " + dataKey, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isOwner() {
|
||||
return UserHandle.myUserId() == UserHandle.USER_OWNER;
|
||||
}
|
||||
|
||||
@@ -59,20 +59,25 @@ public class BatteryOptimizeUtils {
|
||||
mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName);
|
||||
}
|
||||
|
||||
public AppUsageState getAppUsageState() {
|
||||
refreshState();
|
||||
if (!mAllowListed && mMode == AppOpsManager.MODE_IGNORED) {
|
||||
/** Gets the {@link AppUsageState} based on mode and allowed list. */
|
||||
public static AppUsageState getAppUsageState(int mode, boolean isAllowListed) {
|
||||
if (!isAllowListed && mode == AppOpsManager.MODE_IGNORED) {
|
||||
return AppUsageState.RESTRICTED;
|
||||
} else if (mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) {
|
||||
} else if (isAllowListed && mode == AppOpsManager.MODE_ALLOWED) {
|
||||
return AppUsageState.UNRESTRICTED;
|
||||
} else if (!mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) {
|
||||
} else if (!isAllowListed && mode == AppOpsManager.MODE_ALLOWED) {
|
||||
return AppUsageState.OPTIMIZED;
|
||||
} else {
|
||||
Log.d(TAG, "get unknown app usage state.");
|
||||
return AppUsageState.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the current {@link AppUsageState}. */
|
||||
public AppUsageState getAppUsageState() {
|
||||
refreshState();
|
||||
return getAppUsageState(mMode, mAllowListed);
|
||||
}
|
||||
|
||||
public void setAppUsageState(AppUsageState state) {
|
||||
switch (state) {
|
||||
case RESTRICTED:
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
@@ -44,12 +45,14 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl
|
||||
|
||||
private static final String TAG = "NetworkProviderCallsSmsController";
|
||||
private static final String KEY = "calls_and_sms";
|
||||
private static final String RTL_MARK = "\u200F";
|
||||
|
||||
private UserManager mUserManager;
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private SubscriptionsChangeListener mSubscriptionsChangeListener;
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private RestrictedPreference mPreference;
|
||||
private boolean mIsRtlMode;
|
||||
|
||||
/**
|
||||
* The summary text and click behavior of the "Calls & SMS" item on the
|
||||
@@ -61,6 +64,8 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
|
||||
mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
|
||||
== View.LAYOUT_DIRECTION_RTL;
|
||||
if (lifecycle != null) {
|
||||
mSubscriptionsChangeListener = new SubscriptionsChangeListener(context, this);
|
||||
lifecycle.addObserver(this);
|
||||
@@ -121,6 +126,10 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl
|
||||
if (subInfo != subs.get(subs.size() - 1)) {
|
||||
summary.append(", ");
|
||||
}
|
||||
|
||||
if (mIsRtlMode) {
|
||||
summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
|
||||
}
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ package com.android.settings.network;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.widget.PreferenceCategoryController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
@@ -15,6 +17,7 @@ public class NetworkProviderDownloadedSimsCategoryController extends
|
||||
|
||||
private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM =
|
||||
"provider_model_downloaded_sim_category";
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController;
|
||||
|
||||
public NetworkProviderDownloadedSimsCategoryController(Context context, String key) {
|
||||
@@ -44,9 +47,19 @@ public class NetworkProviderDownloadedSimsCategoryController extends
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
PreferenceCategory preferenceCategory = screen.findPreference(
|
||||
mPreferenceCategory = screen.findPreference(
|
||||
KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
|
||||
preferenceCategory.setVisible(isAvailable());
|
||||
mPreferenceCategory.setVisible(isAvailable());
|
||||
mNetworkProviderDownloadedSimListController.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
int count = mPreferenceCategory.getPreferenceCount();
|
||||
String title = mContext.getString(count > 1
|
||||
? R.string.downloaded_sims_category_title
|
||||
: R.string.downloaded_sim_category_title);
|
||||
mPreferenceCategory.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,6 +710,11 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
|
||||
Log.i(TAG, "onWifiStateChanged called with wifi state: " + wifiState);
|
||||
}
|
||||
|
||||
if (isFinishingOrDestroyed()) {
|
||||
Log.w(TAG, "onWifiStateChanged shouldn't run when fragment is finishing or destroyed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (wifiState) {
|
||||
case WifiManager.WIFI_STATE_ENABLED:
|
||||
updateWifiEntryPreferences();
|
||||
@@ -981,6 +986,11 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
|
||||
|
||||
private String getSavedNetworkSettingsSummaryText(
|
||||
int numSavedNetworks, int numSavedSubscriptions) {
|
||||
if (getResources() == null) {
|
||||
Log.w(TAG, "getSavedNetworkSettingsSummaryText shouldn't run if resource is not ready");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (numSavedSubscriptions == 0) {
|
||||
return getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
|
||||
numSavedNetworks, numSavedNetworks);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class CallsDefaultSubscriptionController extends DefaultSubscriptionContr
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
if (Utils.isProviderModelEnabled(mContext)) {
|
||||
return MobileNetworkUtils.getPreferredStatus(mContext, mManager, true);
|
||||
return MobileNetworkUtils.getPreferredStatus(isRtlMode(), mContext, mManager, true);
|
||||
} else {
|
||||
return super.getSummary();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.telecom.PhoneAccountHandle;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
@@ -62,11 +63,14 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
|
||||
private static final ComponentName PSTN_CONNECTION_SERVICE_COMPONENT =
|
||||
new ComponentName("com.android.phone",
|
||||
"com.android.services.telephony.TelephonyConnectionService");
|
||||
private boolean mIsRtlMode;
|
||||
|
||||
public DefaultSubscriptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mManager = context.getSystemService(SubscriptionManager.class);
|
||||
mChangeListener = new SubscriptionsChangeListener(context, this);
|
||||
mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
|
||||
== View.LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
public void init(Lifecycle lifecycle) {
|
||||
@@ -285,4 +289,8 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
|
||||
refreshSummary(mPreference);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRtlMode() {
|
||||
return mIsRtlMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ public class MobileNetworkUtils {
|
||||
"esim.enable_esim_system_ui_by_default";
|
||||
private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
|
||||
"android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
|
||||
private static final String RTL_MARK = "\u200F";
|
||||
|
||||
// The following constants are used to draw signal icon.
|
||||
public static final int NO_CELL_DATA_TYPE_ICON = 0;
|
||||
@@ -922,7 +923,7 @@ public class MobileNetworkUtils {
|
||||
/**
|
||||
* Returns preferred status of Calls & SMS separately when Provider Model is enabled.
|
||||
*/
|
||||
public static CharSequence getPreferredStatus(Context context,
|
||||
public static CharSequence getPreferredStatus(boolean isRtlMode, Context context,
|
||||
SubscriptionManager subscriptionManager, boolean isPreferredCallStatus) {
|
||||
final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(
|
||||
subscriptionManager);
|
||||
@@ -956,6 +957,10 @@ public class MobileNetworkUtils {
|
||||
if (subInfo != subs.get(subs.size() - 1)) {
|
||||
summary.append(", ");
|
||||
}
|
||||
|
||||
if (isRtlMode) {
|
||||
summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
|
||||
}
|
||||
}
|
||||
return summary;
|
||||
} else {
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SmsDefaultSubscriptionController extends DefaultSubscriptionControl
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
if (Utils.isProviderModelEnabled(mContext)) {
|
||||
return MobileNetworkUtils.getPreferredStatus(mContext, mManager, false);
|
||||
return MobileNetworkUtils.getPreferredStatus(isRtlMode(), mContext, mManager, false);
|
||||
} else {
|
||||
return super.getSummary();
|
||||
}
|
||||
|
||||
@@ -27,11 +27,21 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.backup.BackupDataOutput;
|
||||
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.IDeviceIdleController;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -57,13 +67,23 @@ public final class BatteryBackupHelperTest {
|
||||
private BackupDataOutput mBackupDataOutput;
|
||||
@Mock
|
||||
private IDeviceIdleController mDeviceController;
|
||||
@Mock
|
||||
private IPackageManager mIPackageManager;
|
||||
@Mock
|
||||
private AppOpsManager mAppOpsManager;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
doReturn(mContext).when(mContext).getApplicationContext();
|
||||
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
|
||||
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||
mBatteryBackupHelper = new BatteryBackupHelper(mContext);
|
||||
mBatteryBackupHelper.mIDeviceIdleController = mDeviceController;
|
||||
mBatteryBackupHelper.mIPackageManager = mIPackageManager;
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -135,6 +155,78 @@ public final class BatteryBackupHelperTest {
|
||||
verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupOptimizationMode_nullInstalledApps_ignoreBackupOptimization()
|
||||
throws Exception {
|
||||
final UserInfo userInfo =
|
||||
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
|
||||
doReturn(Arrays.asList(userInfo)).when(mUserManager).getProfiles(anyInt());
|
||||
doThrow(new RuntimeException())
|
||||
.when(mIPackageManager)
|
||||
.getInstalledApplications(anyInt(), anyInt());
|
||||
|
||||
mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, null);
|
||||
|
||||
verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupOptimizationMode_backupOptimizationMode() throws Exception {
|
||||
final String packageName1 = "com.android.testing.1";
|
||||
final String packageName2 = "com.android.testing.2";
|
||||
final String packageName3 = "com.android.testing.3";
|
||||
final List<String> allowlistedApps = Arrays.asList(packageName1);
|
||||
createTestingData(packageName1, packageName2, packageName3);
|
||||
|
||||
mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, allowlistedApps);
|
||||
|
||||
final String expectedResult =
|
||||
packageName1 + "|UNRESTRICTED," + packageName2 + "|RESTRICTED,";
|
||||
final byte[] expectedBytes = expectedResult.getBytes();
|
||||
verify(mBackupDataOutput).writeEntityHeader(
|
||||
BatteryBackupHelper.KEY_OPTIMIZATION_LIST, expectedBytes.length);
|
||||
verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
|
||||
}
|
||||
|
||||
private void createTestingData(
|
||||
String packageName1, String packageName2, String packageName3) throws Exception {
|
||||
// Sets the getInstalledApplications() method for testing.
|
||||
final UserInfo userInfo =
|
||||
new UserInfo(/*userId=*/ 0, /*userName=*/ "google", /*flag=*/ 0);
|
||||
doReturn(Arrays.asList(userInfo)).when(mUserManager).getProfiles(anyInt());
|
||||
final ApplicationInfo applicationInfo1 = new ApplicationInfo();
|
||||
applicationInfo1.enabled = true;
|
||||
applicationInfo1.uid = 1;
|
||||
applicationInfo1.packageName = packageName1;
|
||||
final ApplicationInfo applicationInfo2 = new ApplicationInfo();
|
||||
applicationInfo2.enabled = false;
|
||||
applicationInfo2.uid = 2;
|
||||
applicationInfo2.packageName = packageName2;
|
||||
applicationInfo2.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
|
||||
final ApplicationInfo applicationInfo3 = new ApplicationInfo();
|
||||
applicationInfo3.enabled = false;
|
||||
applicationInfo3.uid = 3;
|
||||
applicationInfo3.packageName = packageName3;
|
||||
applicationInfo3.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
||||
doReturn(new ParceledListSlice<ApplicationInfo>(
|
||||
Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3)))
|
||||
.when(mIPackageManager)
|
||||
.getInstalledApplications(anyInt(), anyInt());
|
||||
// Sets the AppOpsManager for checkOpNoThrow() method.
|
||||
doReturn(AppOpsManager.MODE_ALLOWED)
|
||||
.when(mAppOpsManager)
|
||||
.checkOpNoThrow(
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
|
||||
applicationInfo1.uid,
|
||||
applicationInfo1.packageName);
|
||||
doReturn(AppOpsManager.MODE_IGNORED)
|
||||
.when(mAppOpsManager)
|
||||
.checkOpNoThrow(
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
|
||||
applicationInfo2.uid,
|
||||
applicationInfo2.packageName);
|
||||
}
|
||||
|
||||
@Implements(UserHandle.class)
|
||||
public static class ShadowUserHandle {
|
||||
// Sets the default as thte OWNER role.
|
||||
|
||||
Reference in New Issue
Block a user