From 3fb054f3d3df6ed3ca07036720116f9eae4098b7 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 13 Jun 2017 10:17:59 -0700 Subject: [PATCH] Display anomaly in battery usage page This cl adds a new parameter, mAnomalies, for AdvancedPowerUsageDetail. If it is null, fragment will start AnomalyLoader to detect anomaly. If not null, just display the anomaly. Bug: 36925180 Test: RunSettingsRoboTests Change-Id: I572bc5954c1cdb210d18b6dbe1ab9dba25c0a61f --- res/xml/power_usage_detail.xml | 5 ++ .../applications/InstalledAppDetails.java | 2 +- .../fuelgauge/AdvancedPowerUsageDetail.java | 70 +++++++++++++++++-- .../settings/fuelgauge/PowerUsageSummary.java | 3 +- .../AnomalySummaryPreferenceController.java | 5 +- .../AdvancedPowerUsageDetailTest.java | 58 +++++++++++++-- 6 files changed, 127 insertions(+), 16 deletions(-) diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml index b7865d29002..aa1540d1c19 100644 --- a/res/xml/power_usage_detail.xml +++ b/res/xml/power_usage_detail.xml @@ -29,6 +29,11 @@ android:selectable="false" android:order="-9999"/> + + diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index e66463dfe86..b3aacb2b2f4 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -1052,7 +1052,7 @@ public class InstalledAppDetails extends AppInfoBase BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper); AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this, mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, - mBatteryPercent); + mBatteryPercent, null /* mAnomalies */); } else { AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this, mPackageName); diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index 016690c8a2e..0b1d4a8ae9f 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -17,9 +17,11 @@ package com.android.settings.fuelgauge; import android.app.Activity; +import android.app.LoaderManager; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; +import android.content.Loader; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.Bundle; @@ -43,6 +45,10 @@ import com.android.settings.core.PreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.enterprise.DevicePolicyManagerWrapper; import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.fuelgauge.anomaly.AnomalyDialogFragment; +import com.android.settings.fuelgauge.anomaly.AnomalyLoader; +import com.android.settings.fuelgauge.anomaly.AnomalySummaryPreferenceController; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; @@ -55,10 +61,11 @@ import java.util.List; * * 1. Detail battery usage information for app(i.e. usage time, usage amount) * 2. Battery related controls for app(i.e uninstall, force stop) - * */ public class AdvancedPowerUsageDetail extends DashboardFragment implements - ButtonActionDialogFragment.AppButtonsDialogListener { + ButtonActionDialogFragment.AppButtonsDialogListener, + AnomalyDialogFragment.AnomalyDialogListener, + LoaderManager.LoaderCallbacks> { public static final String TAG = "AdvancedPowerUsageDetail"; public static final String EXTRA_UID = "extra_uid"; @@ -69,6 +76,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements public static final String EXTRA_ICON_ID = "extra_icon_id"; public static final String EXTRA_POWER_USAGE_PERCENT = "extra_power_usage_percent"; public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount"; + public static final String EXTRA_ANOMALY_LIST = "extra_anomaly_list"; private static final String KEY_PREF_FOREGROUND = "app_usage_foreground"; private static final String KEY_PREF_BACKGROUND = "app_usage_background"; @@ -78,6 +86,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements private static final int REQUEST_UNINSTALL = 0; private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1; + private static final int ANOMALY_LOADER = 0; + @VisibleForTesting LayoutPreference mHeaderPreference; @VisibleForTesting @@ -93,14 +103,19 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements Preference mBackgroundPreference; @VisibleForTesting Preference mPowerUsagePreference; + @VisibleForTesting + AnomalySummaryPreferenceController mAnomalySummaryPreferenceController; private AppButtonsPreferenceController mAppButtonsPreferenceController; private DevicePolicyManagerWrapper mDpm; private UserManager mUserManager; private PackageManager mPackageManager; + private List mAnomalies; + private String mPackageName; public static void startBatteryDetailPage(SettingsActivity caller, PreferenceFragment fragment, - BatteryStatsHelper helper, int which, BatteryEntry entry, String usagePercent) { + BatteryStatsHelper helper, int which, BatteryEntry entry, String usagePercent, + List anomalies) { // Initialize mStats if necessary. helper.getStats(); @@ -130,6 +145,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements args.putLong(EXTRA_FOREGROUND_TIME, foregroundTimeMs); args.putString(EXTRA_POWER_USAGE_PERCENT, usagePercent); args.putInt(EXTRA_POWER_USAGE_AMOUNT, (int) sipper.totalPowerMah); + args.putParcelableList(EXTRA_ANOMALY_LIST, anomalies); caller.startPreferencePanelAsUser(fragment, AdvancedPowerUsageDetail.class.getName(), args, R.string.battery_details_title, null, @@ -162,14 +178,17 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements public void onCreate(Bundle icicle) { super.onCreate(icicle); + mPackageName = getArguments().getString(EXTRA_PACKAGE_NAME); + mAnomalySummaryPreferenceController = new AnomalySummaryPreferenceController( + (SettingsActivity) getActivity(), this, MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL); mForegroundPreference = findPreference(KEY_PREF_FOREGROUND); mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND); mPowerUsagePreference = findPreference(KEY_PREF_POWER_USAGE); mHeaderPreference = (LayoutPreference) findPreference(KEY_PREF_HEADER); - final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME); - if (packageName != null) { - mAppEntry = mState.getEntry(packageName, UserHandle.myUserId()); + if (mPackageName != null) { + mAppEntry = mState.getEntry(mPackageName, UserHandle.myUserId()); + initAnomalyInfo(); } } @@ -181,6 +200,16 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements initPreference(); } + @VisibleForTesting + void initAnomalyInfo() { + mAnomalies = getArguments().getParcelableArrayList(EXTRA_ANOMALY_LIST); + if (mAnomalies == null) { + getLoaderManager().initLoader(ANOMALY_LOADER, Bundle.EMPTY, this); + } else if (mAnomalies != null){ + mAnomalySummaryPreferenceController.updateAnomalySummaryPreference(mAnomalies); + } + } + @VisibleForTesting void initHeader() { final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header); @@ -234,6 +263,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements getString(R.string.battery_detail_power_percentage, usagePercent, powerMah)); } + @Override + public boolean onPreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), AnomalySummaryPreferenceController.ANOMALY_KEY)) { + mAnomalySummaryPreferenceController.onPreferenceTreeClick(preference); + return true; + } + return super.onPreferenceTreeClick(preference); + } + @Override public int getMetricsCategory() { return MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL; @@ -281,4 +319,24 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements mAppButtonsPreferenceController.handleDialogClick(id); } } + + @Override + public void onAnomalyHandled(Anomaly anomaly) { + mAnomalySummaryPreferenceController.hideHighUsagePreference(); + } + + @Override + public Loader> onCreateLoader(int id, Bundle args) { + return new AnomalyLoader(getContext(), mPackageName); + } + + @Override + public void onLoadFinished(Loader> loader, List data) { + mAnomalySummaryPreferenceController.updateAnomalySummaryPreference(data); + } + + @Override + public void onLoaderReset(Loader> loader) { + + } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 1e4302a35c6..0149e22dce0 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -286,7 +286,8 @@ public class PowerUsageSummary extends PowerUsageBase implements PowerGaugePreference pgp = (PowerGaugePreference) preference; BatteryEntry entry = pgp.getInfo(); AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), - this, mStatsHelper, mStatsType, entry, pgp.getPercent()); + this, mStatsHelper, mStatsType, entry, pgp.getPercent(), + mAnomalySparseArray.get(entry.sipper.getUid())); return super.onPreferenceTreeClick(preference); } diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java b/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java index 23b4e77051f..47c2d2b5e26 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java @@ -32,8 +32,9 @@ import java.util.List; */ public class AnomalySummaryPreferenceController { private static final String TAG = "HighUsagePreferenceController"; - @VisibleForTesting - static final String ANOMALY_KEY = "high_usage"; + + public static final String ANOMALY_KEY = "high_usage"; + private static final int REQUEST_ANOMALY_ACTION = 0; private PreferenceFragment mFragment; @VisibleForTesting diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index d837c40da95..a78c3852422 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -19,6 +19,7 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.eq; @@ -30,6 +31,7 @@ import static org.mockito.Mockito.verify; import android.app.Activity; import android.app.Fragment; +import android.app.LoaderManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -43,6 +45,8 @@ import android.support.v7.widget.RecyclerView; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.SettingsActivity; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.fuelgauge.anomaly.AnomalySummaryPreferenceController; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.applications.LayoutPreference; @@ -68,6 +72,9 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; +import java.util.ArrayList; +import java.util.List; + @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = ShadowEntityHeaderController.class) @@ -108,6 +115,10 @@ public class AdvancedPowerUsageDetailTest { private BatteryStats.Uid mUid; @Mock private PackageManager mPackageManager; + @Mock + private LoaderManager mLoaderManager; + @Mock + private AnomalySummaryPreferenceController mAnomalySummaryPreferenceController; private Context mContext; private Preference mForegroundPreference; private Preference mBackgroundPreference; @@ -115,6 +126,7 @@ public class AdvancedPowerUsageDetailTest { private AdvancedPowerUsageDetail mFragment; private FakeFeatureFactory mFeatureFactory; private SettingsActivity mTestActivity; + private List mAnomalies; @Before public void setUp() { @@ -130,6 +142,7 @@ public class AdvancedPowerUsageDetailTest { doReturn(SUMMARY).when(mFragment).getString(anyInt()); doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class)); doReturn(mBundle).when(mFragment).getArguments(); + doReturn(mLoaderManager).when(mFragment).getLoaderManager(); ShadowEntityHeaderController.setUseMock(mEntityHeaderController); doReturn(mEntityHeaderController).when(mEntityHeaderController) @@ -184,6 +197,11 @@ public class AdvancedPowerUsageDetailTest { mFragment.mForegroundPreference = mForegroundPreference; mFragment.mBackgroundPreference = mBackgroundPreference; mFragment.mPowerUsagePreference = mPowerUsagePreference; + mFragment.mAnomalySummaryPreferenceController = mAnomalySummaryPreferenceController; + + mAnomalies = new ArrayList<>(); + mAnomalies.add(new Anomaly.Builder().setUid(UID).setType( + Anomaly.AnomalyType.WAKE_LOCK).build()); } @After @@ -238,7 +256,7 @@ public class AdvancedPowerUsageDetailTest { @Test public void testStartBatteryDetailPage_hasBasicData() { AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, - mBatteryEntry, USAGE_PERCENT); + mBatteryEntry, USAGE_PERCENT, mAnomalies); assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)).isEqualTo( @@ -247,6 +265,8 @@ public class AdvancedPowerUsageDetailTest { FOREGROUND_TIME_MS); assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo( USAGE_PERCENT); + assertThat(mBundle.getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST)).isEqualTo(mAnomalies); } @Test @@ -255,7 +275,7 @@ public class AdvancedPowerUsageDetailTest { mBatterySipper.usageTimeMs = PHONE_FOREGROUND_TIME_MS; AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, - mBatteryEntry, USAGE_PERCENT); + mBatteryEntry, USAGE_PERCENT, null); assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)).isEqualTo( @@ -264,6 +284,8 @@ public class AdvancedPowerUsageDetailTest { PHONE_BACKGROUND_TIME_MS); assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo( USAGE_PERCENT); + assertThat(mBundle.getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST)).isNull(); } @Test @@ -271,21 +293,25 @@ public class AdvancedPowerUsageDetailTest { mBatterySipper.mPackages = PACKAGE_NAME; mBatteryEntry.defaultPackageName = PACKAGE_NAME[0]; AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, - mBatteryEntry, USAGE_PERCENT); + mBatteryEntry, USAGE_PERCENT, mAnomalies); assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo( PACKAGE_NAME[0]); + assertThat(mBundle.getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST)).isEqualTo(mAnomalies); } @Test public void testStartBatteryDetailPage_SystemApp() { mBatterySipper.mPackages = null; AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, - mBatteryEntry, USAGE_PERCENT); + mBatteryEntry, USAGE_PERCENT, null); assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_LABEL)).isEqualTo(APP_LABEL); assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_ICON_ID)).isEqualTo(ICON_ID); - assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo(null); + assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isNull(); + assertThat(mBundle.getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST)).isNull(); } @Test @@ -294,7 +320,7 @@ public class AdvancedPowerUsageDetailTest { mBatterySipper.mPackages = PACKAGE_NAME; doReturn(appUid).when(mBatterySipper).getUid(); AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, - mBatteryEntry, USAGE_PERCENT); + mBatteryEntry, USAGE_PERCENT, null); verify(mTestActivity).startPreferencePanelAsUser( nullable(Fragment.class), nullable(String.class), nullable(Bundle.class), anyInt(), @@ -344,4 +370,24 @@ public class AdvancedPowerUsageDetailTest { assertThat(mPowerUsagePreference.getSummary()).isEqualTo("16% of total app usage (150mAh)"); } + @Test + public void testInitAnomalyInfo_anomalyNull_startAnomalyLoader() { + doReturn(null).when(mBundle).getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST); + + mFragment.initAnomalyInfo(); + + verify(mLoaderManager).initLoader(eq(0), eq(Bundle.EMPTY), any()); + } + + @Test + public void testInitAnomalyInfo_anomalyExisted_updateAnomaly() { + doReturn(mAnomalies).when(mBundle).getParcelableArrayList( + AdvancedPowerUsageDetail.EXTRA_ANOMALY_LIST); + + mFragment.initAnomalyInfo(); + + verify(mAnomalySummaryPreferenceController).updateAnomalySummaryPreference(mAnomalies); + } + }