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

Commit 75ad2496 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

AppStandby exemption: sync requested by FG apps

Bug: 72443754
Fix: 72443754

Test: atest ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
Test: Manual test with contacts sync:

Precondition: Put the contacts sync in RARE bucket.

adb shell dumpsys deviceidle tempwhitelist -r com.google.android.syncadapters.contacts
adb shell am make-uid-idle com.google.android.syncadapters.contacts
adb shell am set-standby-bucket com.google.android.syncadapters.contacts 40

Test 1: Toggle contacts sync from the Settings -> Account

- Make sure a sync happens.

Test 2: Mutate a contact on the WEB

- Sync is scheduled, but won't run because it has no network access.
- am set-standby-bucket com.google.android.syncadapters.contacts 30
- Sync run runs.

Test 3. adb shell requestsync -n ACCOUNT -t com.google -a com.android.contacts

- Sync is scheduled but won't run.

Test 4. adb shell requestsync -n ACCOUNT -t com.google -a com.android.contacts -f

- Sync is scheduled but it still won't run.

Test 5. adb shell requestsync -n ACCOUNT -t com.google -a com.android.contacts -F

- Sync now runs

Change-Id: I1eb972ed321d2a1a782ae23ccb806671926d3e6b
parent 2011f233
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -29,23 +29,21 @@ public class RequestSync {
    private String[] mArgs;
    private int mNextArg;
    private String mCurArgData;
    private boolean mIsForegroundRequest;

    private int mExemptionFlag = ContentResolver.SYNC_EXEMPTION_NONE;

    enum Operation {
        REQUEST_SYNC {
            @Override
            void invoke(RequestSync caller) {
                if (caller.mIsForegroundRequest) {
                    caller.mExtras.putBoolean(
                            ContentResolver.SYNC_VIRTUAL_EXTRAS_FORCE_FG_SYNC, true);
                } else {
                    caller.mExtras.putBoolean(
                            ContentResolver.SYNC_VIRTUAL_EXTRAS_FORCE_BG_SYNC, true);
                final int flag = caller.mExemptionFlag;
                caller.mExtras.putInt(ContentResolver.SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG, flag);
                if (flag == ContentResolver.SYNC_EXEMPTION_NONE) {
                    System.out.println(
                            "Making a sync request as a background app.\n"
                            + "Note: request may be throttled by App Standby.\n"
                            + "To override this behavior and run a sync immediately,"
                            + " pass a -f option.\n");
                            + " pass a -f or -F option (use -h for help).\n");
                }
                final SyncRequest request =
                        new SyncRequest.Builder()
@@ -213,7 +211,10 @@ public class RequestSync {
                mExtras.putBoolean(key, Boolean.valueOf(value));

            } else if (opt.equals("-f") || opt.equals("--foreground")) {
                mIsForegroundRequest = true;
                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE;

            } else if (opt.equals("-F") || opt.equals("--top")) {
                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;

            } else {
                System.err.println("Error: Unknown option: " + opt);
@@ -293,7 +294,9 @@ public class RequestSync {
                "       -a|--authority <AUTHORITY>\n" +
                "    App-standby related options\n" +
                "\n" +
                "       -f|--foreground (Exempt a sync from app standby)\n" +
                "       -f|--foreground (cause WORKING_SET, FREQUENT sync adapters" +
                        " to run immediately)\n" +
                "       -F|--top (cause even RARE sync adapters to run immediately)\n" +
                "    ContentResolver extra options:\n" +
                "      --is|--ignore-settings: Add SYNC_EXTRAS_IGNORE_SETTINGS\n" +
                "      --ib|--ignore-backoff: Add SYNC_EXTRAS_IGNORE_BACKOFF\n" +
+6 −0
Original line number Diff line number Diff line
@@ -183,10 +183,13 @@ public final class UsageStatsManager {
    public static final int REASON_SUB_USAGE_SLICE_PINNED       = 0x0009;
    /** @hide */
    public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV  = 0x000A;
    /** @hide */
    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000B;

    /** @hide */
    public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;


    /** @hide */
    @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = {
            STANDBY_BUCKET_EXEMPTED,
@@ -665,6 +668,9 @@ public final class UsageStatsManager {
                    case REASON_SUB_USAGE_SLICE_PINNED_PRIV:
                        sb.append("slpp");
                        break;
                    case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
                        sb.append("es");
                        break;
                }
                break;
        }
+8 −0
Original line number Diff line number Diff line
@@ -243,4 +243,12 @@ public abstract class UsageStatsManagerInternal {
     */
    public abstract void reportAppJobState(String packageName, @UserIdInt int userId,
            int numDeferredJobs, long timeSinceLastJobRun);

    /**
     * Report a sync that was scheduled by an active app is about to be executed.
     *
     * @param packageName name of the package that owns the sync adapter.
     * @param userId which user the app is associated with
     */
    public abstract void reportExemptedSyncStart(String packageName, @UserIdInt int userId);
}
+34 −13
Original line number Diff line number Diff line
@@ -166,24 +166,13 @@ public abstract class ContentResolver {
    public static final String SYNC_EXTRAS_DISALLOW_METERED = "allow_metered";

    /**
     * {@hide} Flag only used by the requestsync command to treat a request as if it was made by
     * a foreground app.
     * {@hide} Integer extra containing a SyncExemption flag.
     *
     * Only the system and the shell user can set it.
     *
     * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle.
     */
    public static final String SYNC_VIRTUAL_EXTRAS_FORCE_FG_SYNC = "force_fg_sync";

    /**
     * {@hide} Flag only used by the requestsync command to treat a request as if it was made by
     * a background app.
     *
     * Only the system and the shell user can set it.
     *
     * This extra is "virtual". Once passed to the system server, it'll be removed from the bundle.
     */
    public static final String SYNC_VIRTUAL_EXTRAS_FORCE_BG_SYNC = "force_bg_sync";
    public static final String SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG = "v_exemption";

    /**
     * Set by the SyncManager to request that the SyncAdapter initialize itself for
@@ -525,6 +514,38 @@ public abstract class ContentResolver {
     */
    public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;

    /**
     * No exception, throttled by app standby normally.
     * @hide
     */
    public static final int SYNC_EXEMPTION_NONE = 0;

    /**
     * When executing a sync with this exemption, we'll put the target app in the ACTIVE bucket
     * for 10 minutes. This will allow the sync adapter to schedule/run further syncs and jobs.
     *
     * Note this will still *not* let RARE apps to run syncs, because they still won't get network
     * connection.
     * @hide
     */
    public static final int SYNC_EXEMPTION_ACTIVE = 1;

    /**
     * In addition to {@link #SYNC_EXEMPTION_ACTIVE}, we put the sync adapter app in the
     * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
     * @hide
     */
    public static final int SYNC_EXEMPTION_ACTIVE_WITH_TEMP = 2;

    /** @hide */
    @IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = {
            SYNC_EXEMPTION_NONE,
            SYNC_EXEMPTION_ACTIVE,
            SYNC_EXEMPTION_ACTIVE_WITH_TEMP,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SyncExemption {}

    // Always log queries which take 500ms+; shorter queries are
    // sampled accordingly.
    private static final boolean ENABLE_CONTENT_SAMPLE = false;
+1 −1
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ public final class UserHandle implements Parcelable {
     * @hide
     */
    public static boolean isCore(int uid) {
        if (uid > 0) {
        if (uid >= 0) {
            final int appId = getAppId(uid);
            return appId < Process.FIRST_APPLICATION_UID;
        } else {
Loading