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

Commit 87962f9d authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Unrestrict updated buggy apps." into rvc-dev

parents 48c1ef6e 75e1da7b
Loading
Loading
Loading
Loading
+42 −9
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_APP_UPDATE;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
import static android.app.usage.UsageStatsManager.REASON_SUB_MASK;
import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT;
@@ -73,7 +75,6 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.database.ContentObserver;
import android.hardware.display.DisplayManager;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
@@ -304,10 +305,7 @@ public class AppStandbyController implements AppStandbyInternal {
    private final AppStandbyHandler mHandler;
    private final Context mContext;

    // TODO: Provide a mechanism to set an external bucketing service

    private AppWidgetManager mAppWidgetManager;
    private ConnectivityManager mConnectivityManager;
    private PackageManager mPackageManager;
    Injector mInjector;

@@ -411,7 +409,6 @@ public class AppStandbyController implements AppStandbyInternal {
            settingsObserver.updateSettings();

            mAppWidgetManager = mContext.getSystemService(AppWidgetManager.class);
            mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);

            mInjector.registerDisplayListener(mDisplayListener, mHandler);
            synchronized (mAppIdleLock) {
@@ -1519,6 +1516,38 @@ public class AppStandbyController implements AppStandbyInternal {
        }
    }

    /**
     * Remove an app from the {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
     * bucket if it was forced into the bucket by the system because it was buggy.
     */
    @VisibleForTesting
    void maybeUnrestrictBuggyApp(String packageName, int userId) {
        synchronized (mAppIdleLock) {
            final long elapsedRealtime = mInjector.elapsedRealtime();
            final AppIdleHistory.AppUsageHistory app =
                    mAppIdleHistory.getAppUsageHistory(packageName, userId, elapsedRealtime);
            if (app.currentBucket != STANDBY_BUCKET_RESTRICTED
                    || (app.bucketingReason & REASON_MAIN_MASK) != REASON_MAIN_FORCED_BY_SYSTEM) {
                return;
            }

            final int newBucket;
            final int newReason;
            if ((app.bucketingReason & REASON_SUB_MASK) == REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY) {
                // If bugginess was the only reason the app should be restricted, then lift it out.
                newBucket = STANDBY_BUCKET_RARE;
                newReason = REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_APP_UPDATE;
            } else {
                // There's another reason the app was restricted. Remove the buggy bit and call
                // it a day.
                newBucket = STANDBY_BUCKET_RESTRICTED;
                newReason = app.bucketingReason & ~REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
            }
            mAppIdleHistory.setAppStandbyBucket(
                    packageName, userId, elapsedRealtime, newBucket, newReason);
        }
    }

    private class PackageReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -1528,10 +1557,14 @@ public class AppStandbyController implements AppStandbyInternal {
                clearCarrierPrivilegedApps();
            }
            if ((Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
                    Intent.ACTION_PACKAGE_ADDED.equals(action))
                    && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                clearAppIdleForPackage(intent.getData().getSchemeSpecificPart(),
                        getSendingUserId());
                    Intent.ACTION_PACKAGE_ADDED.equals(action))) {
                final String pkgName = intent.getData().getSchemeSpecificPart();
                final int userId = getSendingUserId();
                if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                    maybeUnrestrictBuggyApp(pkgName, userId);
                } else {
                    clearAppIdleForPackage(pkgName, userId);
                }
            }
        }
    }
+18 −0
Original line number Diff line number Diff line
@@ -203,6 +203,16 @@ public final class UsageStatsManager {

    /** @hide */
    public static final int REASON_SUB_MASK = 0x00FF;
    /**
     * The reason for using the default main reason is unknown or undefined.
     * @hide
     */
    public static final int REASON_SUB_DEFAULT_UNDEFINED = 0x0000;
    /**
     * The app was updated.
     * @hide
     */
    public static final int REASON_SUB_DEFAULT_APP_UPDATE = 0x0001;
    /**
     * The app was interacted with in some way by the system.
     * @hide
@@ -1069,6 +1079,14 @@ public final class UsageStatsManager {
        switch (standbyReason & REASON_MAIN_MASK) {
            case REASON_MAIN_DEFAULT:
                sb.append("d");
                switch (subReason) {
                    case REASON_SUB_DEFAULT_UNDEFINED:
                        // Historically, undefined didn't have a string, so don't add anything here.
                        break;
                    case REASON_SUB_DEFAULT_APP_UPDATE:
                        sb.append("-au");
                        break;
                }
                break;
            case REASON_MAIN_FORCED_BY_SYSTEM:
                sb.append("s");
+74 −0
Original line number Diff line number Diff line
@@ -1208,6 +1208,80 @@ public class AppStandbyControllerTests {
                STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
    }

    public void testAppUpdateOnRestrictedBucketStatus() {
        // Updates shouldn't change bucket if the app timed out.
        // Way past all timeouts. App times out into RESTRICTED bucket.
        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
        mController.checkIdleStates(USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);

        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);

        // Updates shouldn't change bucket if the app was forced by the system for a non-buggy
        // reason.
        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
                REASON_MAIN_FORCED_BY_SYSTEM
                        | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);

        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);

        // Updates should change bucket if the app was forced by the system for a buggy reason.
        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
                REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);

        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
        assertNotEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));

        // Updates shouldn't change bucket if the app was forced by the system for more than just
        // a buggy reason.
        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
                REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE
                        | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);

        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
                getStandbyBucketReason(PACKAGE_1));
        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);

        // Updates shouldn't change bucket if the app was forced by the user.
        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
                REASON_MAIN_FORCED_BY_USER);

        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
        mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
        assertBucket(STANDBY_BUCKET_RESTRICTED);
    }

    private String getAdminAppsStr(int userId) {
        return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
    }