Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit baf8a0cf authored by Lei Yu's avatar Lei Yu
Browse files

Get anomalyType and autoRestriction from config

Now the westworld config provides COOKIES to store private info
for each alert(anomaly). So we could use it to store:
1. AnomalyType: what is the type of anomaly
2. AutoRestriction: whether to auto restrict this anomaly

Bug: 74567790
Test: RunSettingsRoboTests
Change-Id: I15f5e225a4cb1f2da3fe109e56e5222816d179cc
parent 048b71a6
Loading
Loading
Loading
Loading
+35 −19
Original line number Diff line number Diff line
@@ -40,8 +40,11 @@ import android.support.annotation.VisibleForTesting;
import android.util.Log;

import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import com.android.settingslib.utils.ThreadUtils;

@@ -84,11 +87,14 @@ public class AnomalyDetectionJobService extends JobService {
                    true /* collectBatteryBroadcast */);
            final UserManager userManager = getSystemService(UserManager.class);
            final PowerWhitelistBackend powerWhitelistBackend = PowerWhitelistBackend.getInstance();
            final PowerUsageFeatureProvider powerUsageFeatureProvider = FeatureFactory
                    .getFactory(this).getPowerUsageFeatureProvider(this);

            for (JobWorkItem item = params.dequeueWork(); item != null;
                    item = params.dequeueWork()) {
                saveAnomalyToDatabase(batteryStatsHelper, userManager, batteryDatabaseManager,
                        batteryUtils, policy, powerWhitelistBackend, contentResolver,
                        powerUsageFeatureProvider,
                        item.getIntent().getExtras());
            }
            jobFinished(params, false /* wantsReschedule */);
@@ -106,42 +112,52 @@ public class AnomalyDetectionJobService extends JobService {
    void saveAnomalyToDatabase(BatteryStatsHelper batteryStatsHelper, UserManager userManager,
            BatteryDatabaseManager databaseManager, BatteryUtils batteryUtils,
            BatteryTipPolicy policy, PowerWhitelistBackend powerWhitelistBackend,
            ContentResolver contentResolver, Bundle bundle) {
            ContentResolver contentResolver, PowerUsageFeatureProvider powerUsageFeatureProvider,
            Bundle bundle) {
        // The Example of intentDimsValue is: 35:{1:{1:{1:10013|}|}|}
        final StatsDimensionsValue intentDimsValue =
                bundle.getParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE);
        final long subscriptionId = bundle.getLong(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID,
                -1);
        final long timeMs = bundle.getLong(AnomalyDetectionReceiver.KEY_ANOMALY_TIMESTAMP,
                System.currentTimeMillis());
        final String[] cookies = bundle.getStringArray(
                StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES);
        final AnomalyInfo anomalyInfo = new AnomalyInfo(
                !ArrayUtils.isEmpty(cookies) ? cookies[0] : "");
        Log.i(TAG, "Extra stats value: " + intentDimsValue.toString());

        try {
            final int uid = extractUidFromStatsDimensionsValue(intentDimsValue);
            final int anomalyType = StatsManagerConfig.getAnomalyTypeFromSubscriptionId(
                    subscriptionId);
            final boolean smartBatteryOn = Settings.Global.getInt(contentResolver,
                    Settings.Global.APP_STANDBY_ENABLED, ON) == ON;
            final boolean autoFeatureOn = powerUsageFeatureProvider.isSmartBatterySupported()
                    ? Settings.Global.getInt(contentResolver,
                            Settings.Global.APP_STANDBY_ENABLED, ON) == ON
                    : Settings.Global.getInt(contentResolver,
                            Settings.Global.APP_AUTO_RESTRICTION_ENABLED, ON) == ON;
            final String packageName = batteryUtils.getPackageName(uid);
            if (!powerWhitelistBackend.isSysWhitelistedExceptIdle(packageName)
                    && !isSystemUid(uid)) {
                if (anomalyType == StatsManagerConfig.AnomalyType.EXCESSIVE_BG) {
                    // TODO(b/72385333): check battery percentage draining in batterystats
                    if (batteryUtils.isPreOApp(packageName) && batteryUtils.isAppHeavilyUsed(
                            batteryStatsHelper, userManager, uid,
                boolean anomalyDetected = true;
                if (anomalyInfo.anomalyType == StatsManagerConfig.AnomalyType.EXCESSIVE_BG) {
                    if (!batteryUtils.isPreOApp(packageName)
                            || !batteryUtils.isAppHeavilyUsed(batteryStatsHelper, userManager, uid,
                            policy.excessiveBgDrainPercentage)) {
                        Log.e(TAG, "Excessive detected uid=" + uid);
                        // Don't report if it is not legacy app or haven't used much battery
                        anomalyDetected = false;
                    }
                }

                if (anomalyDetected) {
                    if (autoFeatureOn && anomalyInfo.autoRestriction) {
                        // Auto restrict this app
                        batteryUtils.setForceAppStandby(uid, packageName,
                                AppOpsManager.MODE_IGNORED);
                        databaseManager.insertAnomaly(uid, packageName, anomalyType,
                                smartBatteryOn
                                        ? AnomalyDatabaseHelper.State.AUTO_HANDLED
                                        : AnomalyDatabaseHelper.State.NEW,
                        databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
                                AnomalyDatabaseHelper.State.AUTO_HANDLED,
                                timeMs);
                    }
                    } else {
                    databaseManager.insertAnomaly(uid, packageName, anomalyType,
                            AnomalyDatabaseHelper.State.NEW, timeMs);
                        databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
                                AnomalyDatabaseHelper.State.NEW,
                                timeMs);
                    }
                }
            }
        } catch (NullPointerException | IndexOutOfBoundsException e) {
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.fuelgauge.batterytip;

import android.util.KeyValueListParser;

/**
 * Model class to parse and store anomaly info from westworld
 */
public class AnomalyInfo {
    private static final String KEY_ANOMALY_TYPE = "anomaly_type";
    private static final String KEY_AUTO_RESTRICTION = "auto_restriction";
    public final Integer anomalyType;
    public final boolean autoRestriction;

    public AnomalyInfo(String info) {
        KeyValueListParser parser = new KeyValueListParser(',');
        parser.setString(info);
        anomalyType = parser.getInt(KEY_ANOMALY_TYPE, -1);
        autoRestriction = parser.getBoolean(KEY_AUTO_RESTRICTION, false);
    }

}
 No newline at end of file
+0 −23
Original line number Diff line number Diff line
@@ -41,22 +41,6 @@ public class StatsManagerConfig {
     */
    public static final long SUBSCRIBER_ID = 1;

    private static final Map<Long, Integer> ANOMALY_TYPE;

    private static final HashFunction HASH_FUNCTION = Hashing.sha256();

    static {
        ANOMALY_TYPE = new HashMap<>();
        ANOMALY_TYPE.put(hash("SUBSCRIPTION:SETTINGS_EXCESSIVE_BACKGROUND_SERVICE"),
                AnomalyType.EXCESSIVE_BG);
        ANOMALY_TYPE.put(hash("SUBSCRIPTION:SETTINGS_LONG_UNOPTIMIZED_BLE_SCAN"),
                AnomalyType.BLUETOOTH_SCAN);
        ANOMALY_TYPE.put(hash("SUBSCRIPTION:SETTINGS_EXCESSIVE_WAKEUPS_IN_BACKGROUND"),
                AnomalyType.WAKEUP_ALARM);
        ANOMALY_TYPE.put(hash("SUBSCRIPTION:SETTINGS_EXCESSIVE_WAKELOCK_ALL_SCREEN_OFF"),
                AnomalyType.WAKE_LOCK);
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({AnomalyType.NULL,
            AnomalyType.WAKE_LOCK,
@@ -71,11 +55,4 @@ public class StatsManagerConfig {
        int EXCESSIVE_BG = 3;
    }

    public static int getAnomalyTypeFromSubscriptionId(long subscriptionId) {
        return ANOMALY_TYPE.getOrDefault(subscriptionId, AnomalyType.NULL);
    }

    private static long hash(CharSequence value) {
        return HASH_FUNCTION.hashUnencodedChars(value).asLong();
    }
}
+35 −6
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -41,6 +42,8 @@ import android.os.UserManager;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;

@@ -60,6 +63,10 @@ import java.util.concurrent.TimeUnit;
public class AnomalyDetectionJobServiceTest {
    private static final int UID = 123;
    private static final String SYSTEM_PACKAGE = "com.android.system";
    private static final String SUBSCRIBER_COOKIES_AUTO_RESTRICTION =
            "anomaly_type=6,auto_restriction=true";
    private static final String SUBSCRIBER_COOKIES_NOT_AUTO_RESTRICTION =
            "anomaly_type=6,auto_restriction=false";
    @Mock
    private BatteryStatsHelper mBatteryStatsHelper;
    @Mock
@@ -76,6 +83,7 @@ public class AnomalyDetectionJobServiceTest {
    private BatteryTipPolicy mPolicy;
    private Bundle mBundle;
    private AnomalyDetectionJobService mAnomalyDetectionJobService;
    private FakeFeatureFactory mFeatureFactory;
    private Context mContext;

    @Before
@@ -86,6 +94,7 @@ public class AnomalyDetectionJobServiceTest {
        mPolicy = new BatteryTipPolicy(mContext);
        mBundle = new Bundle();
        mBundle.putParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, mStatsDimensionsValue);
        mFeatureFactory = FakeFeatureFactory.setupForTest();

        mAnomalyDetectionJobService = spy(new AnomalyDetectionJobService());
    }
@@ -112,7 +121,7 @@ public class AnomalyDetectionJobServiceTest {

        mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
                mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
                mContext.getContentResolver(), mBundle);
                mContext.getContentResolver(), mFeatureFactory.powerUsageFeatureProvider, mBundle);

        verify(mBatteryDatabaseManager, never()).insertAnomaly(anyInt(), anyString(), anyInt(),
                anyInt(), anyLong());
@@ -125,14 +134,16 @@ public class AnomalyDetectionJobServiceTest {

        mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
                mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
                mContext.getContentResolver(), mBundle);
                mContext.getContentResolver(), mFeatureFactory.powerUsageFeatureProvider, mBundle);

        verify(mBatteryDatabaseManager, never()).insertAnomaly(anyInt(), anyString(), anyInt(),
                anyInt(), anyLong());
    }

    @Test
    public void testSaveAnomalyToDatabase_normalApp_save() {
    public void testSaveAnomalyToDatabase_normalAppWithAutoRestriction_save() {
        mBundle.putStringArray(StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES,
                new String[]{SUBSCRIBER_COOKIES_AUTO_RESTRICTION});
        doReturn(SYSTEM_PACKAGE).when(mBatteryUtils).getPackageName(anyInt());
        doReturn(false).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE);
        doReturn(Process.FIRST_APPLICATION_UID).when(
@@ -140,9 +151,27 @@ public class AnomalyDetectionJobServiceTest {

        mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
                mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
                mContext.getContentResolver(), mBundle);
                mContext.getContentResolver(), mFeatureFactory.powerUsageFeatureProvider, mBundle);

        verify(mBatteryDatabaseManager).insertAnomaly(anyInt(), anyString(), anyInt(), anyInt(),
                anyLong());
        verify(mBatteryDatabaseManager).insertAnomaly(anyInt(), anyString(), eq(6),
                eq(AnomalyDatabaseHelper.State.AUTO_HANDLED), anyLong());
    }


    @Test
    public void testSaveAnomalyToDatabase_normalAppWithoutAutoRestriction_save() {
        mBundle.putStringArray(StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES,
                new String[]{SUBSCRIBER_COOKIES_NOT_AUTO_RESTRICTION});
        doReturn(SYSTEM_PACKAGE).when(mBatteryUtils).getPackageName(anyInt());
        doReturn(false).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE);
        doReturn(Process.FIRST_APPLICATION_UID).when(
                mAnomalyDetectionJobService).extractUidFromStatsDimensionsValue(any());

        mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager,
                mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend,
                mContext.getContentResolver(), mFeatureFactory.powerUsageFeatureProvider, mBundle);

        verify(mBatteryDatabaseManager).insertAnomaly(anyInt(), anyString(), eq(6),
                eq(AnomalyDatabaseHelper.State.NEW), anyLong());
    }
}