From 65cfcbe4864eba17cdab8ed9a9b9797528ce069a Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Wed, 1 Feb 2023 18:46:05 +0800 Subject: [PATCH] Only log the names of the app packages which are installed from Google Play Store in battery usage app optimization page This is to meet the Guidelines for Logging Package Names: go/package-name-logging-guidance Bug: 267430574 Fix: 267430574 Test: presubmit Change-Id: Icf10000f5dcf87e45175d4005af8365191ad444d --- .../fuelgauge/AdvancedPowerUsageDetail.java | 44 ++++++++++++------- .../settings/fuelgauge/BatteryUtils.java | 19 ++++++++ .../AdvancedPowerUsageDetailTest.java | 34 ++++++++------ 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index f3c64b78893..7fe180d0343 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -25,7 +25,6 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.UserHandle; -import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -56,6 +55,8 @@ import com.android.settingslib.widget.SelectorWithWidgetPreference; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * 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_REMOVE_DEVICE_ADMIN = 1; + private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + @VisibleForTesting LayoutPreference mHeaderPreference; @VisibleForTesting @@ -98,8 +101,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements @VisibleForTesting ApplicationsState.AppEntry mAppEntry; @VisibleForTesting - BatteryUtils mBatteryUtils; - @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils; @VisibleForTesting FooterPreference mFooterPreference; @@ -244,7 +245,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements super.onAttach(activity); mState = ApplicationsState.getInstance(getActivity().getApplication()); - mBatteryUtils = BatteryUtils.getInstance(getContext()); } @Override @@ -267,12 +267,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements initHeader(); mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode(); initPreferenceForTriState(getContext()); - final String packageName = mBatteryOptimizeUtils.getPackageName(); - FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider() - .action( - getContext(), - SettingsEnums.OPEN_APP_BATTERY_USAGE, - packageName); + mExecutor.execute(() -> { + String packageName = + getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName()); + FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider() + .action( + getContext(), + SettingsEnums.OPEN_APP_BATTERY_USAGE, + packageName); + }); mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode); } @@ -444,17 +447,21 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED; break; } - - if (metricCategory != 0) { - final String packageName = mBatteryOptimizeUtils.getPackageName(); + if (metricCategory == 0) { + return; + } + int finalMetricCategory = metricCategory; + mExecutor.execute(() -> { + String packageName = + getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName()); FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider() .action( /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE, - /* action */ metricCategory, + /* action */ finalMetricCategory, /* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE, - TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName, + packageName, getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT)); - } + }); } private void onCreateForTriState(String packageName) { @@ -498,4 +505,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements 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; + } } diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index 98defbd3ace..fe396bd6009 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.content.pm.InstallSourceInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -34,6 +35,7 @@ import android.os.SystemClock; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Base64; import android.util.Log; @@ -83,6 +85,8 @@ public class BatteryUtils { 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) @IntDef({StatusType.SCREEN_USAGE, StatusType.FOREGROUND, @@ -597,6 +601,21 @@ public class BatteryUtils { 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. */ public static Intent getBatteryIntent(Context context) { return context.registerReceiver( diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index 6363a8faa62..0278553b2a5 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -20,9 +20,8 @@ import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENT 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.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -38,9 +37,9 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.InstallSourceInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; -import android.os.BatteryStats; import android.os.Bundle; import android.os.Process; import android.os.UserHandle; @@ -79,6 +78,8 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; +import java.util.concurrent.TimeUnit; + @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowEntityHeaderController.class, ShadowActivityManager.class}) public class AdvancedPowerUsageDetailTest { @@ -116,12 +117,12 @@ public class AdvancedPowerUsageDetailTest { @Mock private PackageManager mPackageManager; @Mock + private InstallSourceInfo mInstallSourceInfo; + @Mock private AppOpsManager mAppOpsManager; @Mock private LoaderManager mLoaderManager; @Mock - private BatteryUtils mBatteryUtils; - @Mock private BatteryOptimizeUtils mBatteryOptimizeUtils; @Mock private BackupManager mBackupManager; @@ -179,7 +180,6 @@ public class AdvancedPowerUsageDetailTest { mFragment.mHeaderPreference = mHeaderPreference; mFragment.mState = mState; - mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application); mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils; mFragment.mBackupManager = mBackupManager; mFragment.mLogStringBuilder = new StringBuilder(); @@ -190,10 +190,6 @@ public class AdvancedPowerUsageDetailTest { doReturn(mPackageManager).when(mActivity).getPackageManager(); 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 captor = ArgumentCaptor.forClass(Intent.class); Answer callable = invocation -> { @@ -757,34 +753,46 @@ public class AdvancedPowerUsageDetailTest { } @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; mFragment.mOptimizationMode = 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); mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onPause(); + TimeUnit.SECONDS.sleep(100); verify(mMetricsFeatureProvider) .action( SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED, SettingsEnums.OPEN_APP_BATTERY_USAGE, - /* package name*/ "none", + packageName, /* consumed battery */ 0); } @Test - public void onPause_optimizationModeIsNotChanged_notInvokeLogging() { + public void onPause_optimizationModeIsNotChanged_notInvokeLogging() + throws PackageManager.NameNotFoundException, InterruptedException { final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED; mFragment.mOptimizationMode = 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); mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onPause(); + TimeUnit.SECONDS.sleep(100); verifyNoInteractions(mMetricsFeatureProvider); }