Add whitelist for anomaly detection.

Even though we can add whitelist in config, we still need to have a
on device whitelist to reduce the size of config.

Use doze whitelist here because we already used it to detect whether
we can restrict the app in battery detail page.

Bug: 74241534
Test: RunSettingsRoboTests
Change-Id: I35b6f3eba9fbc8ae51bb02cd9d5416e4360c388e
This commit is contained in:
jackqdyulei
2018-03-06 13:19:15 -08:00
committed by Lei Yu
parent 3c5aeac39f
commit 10051afb96
3 changed files with 105 additions and 24 deletions

View File

@@ -41,6 +41,7 @@ import android.util.Log;
import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import java.util.List; import java.util.List;
@@ -81,11 +82,12 @@ public class AnomalyDetectionJobService extends JobService {
final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(this, final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(this,
true /* collectBatteryBroadcast */); true /* collectBatteryBroadcast */);
final UserManager userManager = getSystemService(UserManager.class); final UserManager userManager = getSystemService(UserManager.class);
final PowerWhitelistBackend powerWhitelistBackend = PowerWhitelistBackend.getInstance();
for (JobWorkItem item = params.dequeueWork(); item != null; for (JobWorkItem item = params.dequeueWork(); item != null;
item = params.dequeueWork()) { item = params.dequeueWork()) {
saveAnomalyToDatabase(batteryStatsHelper, userManager, batteryDatabaseManager, saveAnomalyToDatabase(batteryStatsHelper, userManager, batteryDatabaseManager,
batteryUtils, policy, contentResolver, batteryUtils, policy, powerWhitelistBackend, contentResolver,
item.getIntent().getExtras()); item.getIntent().getExtras());
} }
jobFinished(params, false /* wantsReschedule */); jobFinished(params, false /* wantsReschedule */);
@@ -102,7 +104,8 @@ public class AnomalyDetectionJobService extends JobService {
@VisibleForTesting @VisibleForTesting
void saveAnomalyToDatabase(BatteryStatsHelper batteryStatsHelper, UserManager userManager, void saveAnomalyToDatabase(BatteryStatsHelper batteryStatsHelper, UserManager userManager,
BatteryDatabaseManager databaseManager, BatteryUtils batteryUtils, BatteryDatabaseManager databaseManager, BatteryUtils batteryUtils,
BatteryTipPolicy policy, ContentResolver contentResolver, Bundle bundle) { BatteryTipPolicy policy, PowerWhitelistBackend powerWhitelistBackend,
ContentResolver contentResolver, Bundle bundle) {
// The Example of intentDimsValue is: 35:{1:{1:{1:10013|}|}|} // The Example of intentDimsValue is: 35:{1:{1:{1:10013|}|}|}
final StatsDimensionsValue intentDimsValue = final StatsDimensionsValue intentDimsValue =
bundle.getParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE); bundle.getParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE);
@@ -119,7 +122,7 @@ public class AnomalyDetectionJobService extends JobService {
final boolean smartBatteryOn = Settings.Global.getInt(contentResolver, final boolean smartBatteryOn = Settings.Global.getInt(contentResolver,
Settings.Global.APP_STANDBY_ENABLED, ON) == ON; Settings.Global.APP_STANDBY_ENABLED, ON) == ON;
final String packageName = batteryUtils.getPackageName(uid); final String packageName = batteryUtils.getPackageName(uid);
if (!powerWhitelistBackend.isSysWhitelisted(packageName)) {
if (anomalyType == StatsManagerConfig.AnomalyType.EXCESSIVE_BG) { if (anomalyType == StatsManagerConfig.AnomalyType.EXCESSIVE_BG) {
// TODO(b/72385333): check battery percentage draining in batterystats // TODO(b/72385333): check battery percentage draining in batterystats
if (batteryUtils.isLegacyApp(packageName) && batteryUtils.isAppHeavilyUsed( if (batteryUtils.isLegacyApp(packageName) && batteryUtils.isAppHeavilyUsed(
@@ -138,6 +141,7 @@ public class AnomalyDetectionJobService extends JobService {
databaseManager.insertAnomaly(uid, packageName, anomalyType, databaseManager.insertAnomaly(uid, packageName, anomalyType,
AnomalyDatabaseHelper.State.NEW, timeMs); AnomalyDatabaseHelper.State.NEW, timeMs);
} }
}
} catch (NullPointerException | IndexOutOfBoundsException e) { } catch (NullPointerException | IndexOutOfBoundsException e) {
Log.e(TAG, "Parse stats dimensions value error.", e); Log.e(TAG, "Parse stats dimensions value error.", e);
} }

View File

@@ -18,10 +18,10 @@ package com.android.settings.fuelgauge.batterytip;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.ANOMALY_STATE; .ANOMALY_STATE;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.PACKAGE_NAME;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.ANOMALY_TYPE; .ANOMALY_TYPE;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.PACKAGE_NAME;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
.TIME_STAMP_MS; .TIME_STAMP_MS;
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns.UID; import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns.UID;
@@ -61,6 +61,7 @@ public class BatteryDatabaseManager {
/** /**
* Insert an anomaly log to database. * Insert an anomaly log to database.
*
* @param packageName the package name of the app * @param packageName the package name of the app
* @param type the type of the anomaly * @param type the type of the anomaly
* @param anomalyState the state of the anomaly * @param anomalyState the state of the anomaly

View File

@@ -17,17 +17,36 @@
package com.android.settings.fuelgauge.batterytip; package com.android.settings.fuelgauge.batterytip;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.robolectric.RuntimeEnvironment.application; import static org.robolectric.RuntimeEnvironment.application;
import android.app.StatsManager;
import android.app.job.JobInfo; import android.app.job.JobInfo;
import android.app.job.JobScheduler; import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.os.StatsDimensionsValue;
import android.os.UserManager;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows; import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowJobScheduler; import org.robolectric.shadows.ShadowJobScheduler;
@@ -36,6 +55,37 @@ import java.util.concurrent.TimeUnit;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class AnomalyDetectionJobServiceTest { public class AnomalyDetectionJobServiceTest {
private static final int UID = 123;
private static final String SYSTEM_PACKAGE = "com.android.system";
@Mock
private BatteryStatsHelper mBatteryStatsHelper;
@Mock
private UserManager mUserManager;
@Mock
private BatteryDatabaseManager mBatteryDatabaseManager;
@Mock
private BatteryUtils mBatteryUtils;
@Mock
private PowerWhitelistBackend mPowerWhitelistBackend;
@Mock
private StatsDimensionsValue mStatsDimensionsValue;
private BatteryTipPolicy mPolicy;
private Bundle mBundle;
private AnomalyDetectionJobService mAnomalyDetectionJobService;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPolicy = new BatteryTipPolicy(mContext);
mBundle = new Bundle();
mBundle.putParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, mStatsDimensionsValue);
mAnomalyDetectionJobService = new AnomalyDetectionJobService();
}
@Test @Test
public void testScheduleCleanUp() { public void testScheduleCleanUp() {
@@ -50,4 +100,30 @@ public class AnomalyDetectionJobServiceTest {
assertThat(pendingJob.getMaxExecutionDelayMillis()) assertThat(pendingJob.getMaxExecutionDelayMillis())
.isEqualTo(TimeUnit.MINUTES.toMillis(30)); .isEqualTo(TimeUnit.MINUTES.toMillis(30));
} }
@Test
public void testSaveAnomalyToDatabase_systemWhitelisted_doNotSave() {
doReturn(SYSTEM_PACKAGE).when(mBatteryUtils).getPackageName(anyInt());
doReturn(true).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE);
mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
mContext.getContentResolver(), mBundle);
verify(mBatteryDatabaseManager, never()).insertAnomaly(anyInt(), anyString(), anyInt(),
anyInt(), anyLong());
}
@Test
public void testSaveAnomalyToDatabase_normalApp_save() {
doReturn(SYSTEM_PACKAGE).when(mBatteryUtils).getPackageName(anyInt());
doReturn(false).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE);
mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
mContext.getContentResolver(), mBundle);
verify(mBatteryDatabaseManager).insertAnomaly(anyInt(), anyString(), anyInt(), anyInt(),
anyLong());
}
} }