Merge "Only log the names of the app packages which are installed from Google Play Store in battery usage app optimization page"

This commit is contained in:
TreeHugger Robot
2023-02-02 09:55:17 +00:00
committed by Android (Google) Code Review
3 changed files with 68 additions and 29 deletions

View File

@@ -25,7 +25,6 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -56,6 +55,8 @@ import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** /**
* Power usage detail fragment for each app, this fragment contains * Power usage detail fragment for each app, this fragment contains
@@ -91,6 +92,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
private static final int REQUEST_UNINSTALL = 0; private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1; private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting @VisibleForTesting
LayoutPreference mHeaderPreference; LayoutPreference mHeaderPreference;
@VisibleForTesting @VisibleForTesting
@@ -98,8 +101,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@VisibleForTesting @VisibleForTesting
ApplicationsState.AppEntry mAppEntry; ApplicationsState.AppEntry mAppEntry;
@VisibleForTesting @VisibleForTesting
BatteryUtils mBatteryUtils;
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils; BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting @VisibleForTesting
FooterPreference mFooterPreference; FooterPreference mFooterPreference;
@@ -244,7 +245,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
super.onAttach(activity); super.onAttach(activity);
mState = ApplicationsState.getInstance(getActivity().getApplication()); mState = ApplicationsState.getInstance(getActivity().getApplication());
mBatteryUtils = BatteryUtils.getInstance(getContext());
} }
@Override @Override
@@ -267,12 +267,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
initHeader(); initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode(); mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
initPreferenceForTriState(getContext()); initPreferenceForTriState(getContext());
final String packageName = mBatteryOptimizeUtils.getPackageName(); mExecutor.execute(() -> {
String packageName =
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider() FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
.action( .action(
getContext(), getContext(),
SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.OPEN_APP_BATTERY_USAGE,
packageName); packageName);
});
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode); mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
} }
@@ -444,17 +447,21 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED; metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
break; break;
} }
if (metricCategory == 0) {
if (metricCategory != 0) { return;
final String packageName = mBatteryOptimizeUtils.getPackageName(); }
int finalMetricCategory = metricCategory;
mExecutor.execute(() -> {
String packageName =
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider() FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
.action( .action(
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE, /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
/* action */ metricCategory, /* action */ finalMetricCategory,
/* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE, /* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName, packageName,
getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT)); getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
} });
} }
private void onCreateForTriState(String packageName) { private void onCreateForTriState(String packageName) {
@@ -498,4 +505,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
return String.format("%s\n(%s)", usageSummary, slotSummary); return String.format("%s\n(%s)", usageSummary, slotSummary);
} }
} }
private static String getLoggingPackageName(Context context, String originalPackingName) {
return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
? originalPackingName : PACKAGE_NAME_NONE;
}
} }

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -34,6 +35,7 @@ import android.os.SystemClock;
import android.os.UidBatteryConsumer; import android.os.UidBatteryConsumer;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
@@ -83,6 +85,8 @@ public class BatteryUtils {
public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass"; public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass";
private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({StatusType.SCREEN_USAGE, @IntDef({StatusType.SCREEN_USAGE,
StatusType.FOREGROUND, StatusType.FOREGROUND,
@@ -597,6 +601,21 @@ public class BatteryUtils {
return -1L; return -1L;
} }
/** Whether the package is installed from Google Play Store or not */
public static boolean isAppInstalledFromGooglePlayStore(Context context, String packageName) {
if (TextUtils.isEmpty(packageName)) {
return false;
}
InstallSourceInfo installSourceInfo;
try {
installSourceInfo = context.getPackageManager().getInstallSourceInfo(packageName);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
return installSourceInfo != null
&& GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName());
}
/** Gets the latest sticky battery intent from the Android system. */ /** Gets the latest sticky battery intent from the Android system. */
public static Intent getBatteryIntent(Context context) { public static Intent getBatteryIntent(Context context) {
return context.registerReceiver( return context.registerReceiver(

View File

@@ -20,9 +20,8 @@ import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENT
import static com.google.common.truth.Truth.assertThat; 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.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
@@ -38,9 +37,9 @@ import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process; import android.os.Process;
import android.os.UserHandle; import android.os.UserHandle;
@@ -79,6 +78,8 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowActivityManager.class}) @Config(shadows = {ShadowEntityHeaderController.class, ShadowActivityManager.class})
public class AdvancedPowerUsageDetailTest { public class AdvancedPowerUsageDetailTest {
@@ -116,12 +117,12 @@ public class AdvancedPowerUsageDetailTest {
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@Mock @Mock
private InstallSourceInfo mInstallSourceInfo;
@Mock
private AppOpsManager mAppOpsManager; private AppOpsManager mAppOpsManager;
@Mock @Mock
private LoaderManager mLoaderManager; private LoaderManager mLoaderManager;
@Mock @Mock
private BatteryUtils mBatteryUtils;
@Mock
private BatteryOptimizeUtils mBatteryOptimizeUtils; private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock @Mock
private BackupManager mBackupManager; private BackupManager mBackupManager;
@@ -179,7 +180,6 @@ public class AdvancedPowerUsageDetailTest {
mFragment.mHeaderPreference = mHeaderPreference; mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState; mFragment.mState = mState;
mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application);
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils; mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mFragment.mBackupManager = mBackupManager; mFragment.mBackupManager = mBackupManager;
mFragment.mLogStringBuilder = new StringBuilder(); mFragment.mLogStringBuilder = new StringBuilder();
@@ -190,10 +190,6 @@ public class AdvancedPowerUsageDetailTest {
doReturn(mPackageManager).when(mActivity).getPackageManager(); doReturn(mPackageManager).when(mActivity).getPackageManager();
doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE); doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
mBatteryUtils = spy(new BatteryUtils(mContext));
doReturn(FOREGROUND_SERVICE_TIME_US).when(mBatteryUtils).getForegroundServiceTotalTimeUs(
any(BatteryStats.Uid.class), anyLong());
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
Answer<Void> callable = invocation -> { Answer<Void> callable = invocation -> {
@@ -757,34 +753,46 @@ public class AdvancedPowerUsageDetailTest {
} }
@Test @Test
public void onPause_optimizationModeChanged_logPreference() { public void onPause_optimizationModeChanged_logPreference()
throws PackageManager.NameNotFoundException, InterruptedException {
final String packageName = "testPackageName";
final int mode = BatteryOptimizeUtils.MODE_RESTRICTED; final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
mFragment.mOptimizationMode = mode; mFragment.mOptimizationMode = mode;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED); mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onRadioButtonClicked(mOptimizePreference);
mFragment.onPause(); mFragment.onPause();
TimeUnit.SECONDS.sleep(100);
verify(mMetricsFeatureProvider) verify(mMetricsFeatureProvider)
.action( .action(
SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.OPEN_APP_BATTERY_USAGE,
SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED, SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED,
SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.OPEN_APP_BATTERY_USAGE,
/* package name*/ "none", packageName,
/* consumed battery */ 0); /* consumed battery */ 0);
} }
@Test @Test
public void onPause_optimizationModeIsNotChanged_notInvokeLogging() { public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
throws PackageManager.NameNotFoundException, InterruptedException {
final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED; final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED;
mFragment.mOptimizationMode = mode; mFragment.mOptimizationMode = mode;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED); mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onRadioButtonClicked(mOptimizePreference);
mFragment.onPause(); mFragment.onPause();
TimeUnit.SECONDS.sleep(100);
verifyNoInteractions(mMetricsFeatureProvider); verifyNoInteractions(mMetricsFeatureProvider);
} }