Loading apex/jobscheduler/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ java_library { static_libs: [ "modules-utils-fastxmlserializer", "service-jobscheduler-alarm.flags-aconfig-java", "service-jobscheduler-job.flags-aconfig-java", ], Loading apex/jobscheduler/service/aconfig/Android.bp +12 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,15 @@ java_aconfig_library { aconfig_declarations: "service-job.flags-aconfig", visibility: ["//frameworks/base:__subpackages__"], } // Alarm aconfig_declarations { name: "alarm_flags", package: "com.android.server.alarm", srcs: ["alarm.aconfig"], } java_aconfig_library { name: "service-jobscheduler-alarm.flags-aconfig-java", aconfig_declarations: "alarm_flags", } apex/jobscheduler/service/aconfig/alarm.aconfig 0 → 100644 +11 −0 Original line number Diff line number Diff line package: "com.android.server.alarm" flag { name: "use_frozen_state_to_drop_listener_alarms" namespace: "backstage_power" description: "Use frozen state callback to drop listener alarms for cached apps" bug: "324470945" metadata { purpose: PURPOSE_BUGFIX } } apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +65 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.alarm; import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; Loading Loading @@ -75,6 +76,7 @@ import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AlarmManager; Loading Loading @@ -103,6 +105,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Looper; import android.os.Message; Loading Loading @@ -145,6 +148,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.LocalLog; Loading Loading @@ -293,6 +297,7 @@ public class AlarmManagerService extends SystemService { private final Injector mInjector; int mBroadcastRefCount = 0; boolean mUseFrozenStateToDropListenerAlarms; MetricsHelper mMetricsHelper; PowerManager.WakeLock mWakeLock; SparseIntArray mAlarmsPerUid = new SparseIntArray(); Loading Loading @@ -1856,15 +1861,47 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mHandler = new AlarmHandler(); mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithFgsForAlarmClock.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false); mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mMetricsHelper = new MetricsHelper(getContext(), mLock); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mUseFrozenStateToDropListenerAlarms = Flags.useFrozenStateToDropListenerAlarms(); if (mUseFrozenStateToDropListenerAlarms) { final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> { final int size = frozenStates.length; if (uids.length != size) { Slog.wtf(TAG, "Got different length arrays in frozen state callback!" + " uids.length: " + uids.length + " frozenStates.length: " + size); // Cannot process received data in any meaningful way. return; } final IntArray affectedUids = new IntArray(); for (int i = 0; i < size; i++) { if (frozenStates[i] != UID_FROZEN_STATE_FROZEN) { continue; } if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uids[i])) { continue; } affectedUids.add(uids[i]); } if (affectedUids.size() > 0) { removeExactListenerAlarms(affectedUids.toArray()); } }; final ActivityManager am = getContext().getSystemService(ActivityManager.class); am.registerUidFrozenStateChangedCallback(new HandlerExecutor(mHandler), callback); } mListenerDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { Loading @@ -1880,7 +1917,6 @@ public class AlarmManagerService extends SystemService { }; synchronized (mLock) { mHandler = new AlarmHandler(); mConstants = new Constants(mHandler); mAlarmStore = new LazyAlarmStore(); Loading Loading @@ -1960,6 +1996,21 @@ public class AlarmManagerService extends SystemService { publishBinderService(Context.ALARM_SERVICE, mService); } private void removeExactListenerAlarms(int... whichUids) { synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (!ArrayUtils.contains(whichUids, a.uid) || a.listener == null || a.windowLength != 0) { return false; } Slog.w(TAG, "Alarm " + a.listenerTag + " being removed for " + UserHandle.formatUid(a.uid) + ":" + a.packageName + " because the app got frozen"); return true; }, REMOVE_REASON_LISTENER_CACHED); } } void refreshExactAlarmCandidates() { final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages( Manifest.permission.SCHEDULE_EXACT_ALARM); Loading Loading @@ -3074,6 +3125,14 @@ public class AlarmManagerService extends SystemService { mConstants.dump(pw); pw.println(); pw.println("Feature Flags:"); pw.increaseIndent(); pw.print(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS, mUseFrozenStateToDropListenerAlarms); pw.decreaseIndent(); pw.println(); pw.println(); if (mConstants.USE_TARE_POLICY == EconomyManager.ENABLED_MODE_ON) { pw.println("TARE details:"); pw.increaseIndent(); Loading Loading @@ -4959,18 +5018,7 @@ public class AlarmManagerService extends SystemService { break; case REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED: uid = (Integer) msg.obj; synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (a.uid != uid || a.listener == null || a.windowLength != 0) { return false; } // TODO (b/265195908): Change to .w once we have some data on breakages. Slog.wtf(TAG, "Alarm " + a.listenerTag + " being removed for " + UserHandle.formatUid(a.uid) + ":" + a.packageName + " because the app went into cached state"); return true; }, REMOVE_REASON_LISTENER_CACHED); } removeExactListenerAlarms(uid); break; default: // nope, just ignore it Loading Loading @@ -5322,6 +5370,10 @@ public class AlarmManagerService extends SystemService { @Override public void handleUidCachedChanged(int uid, boolean cached) { if (mUseFrozenStateToDropListenerAlarms) { // Use ActivityManager#UidFrozenStateChangedCallback instead. return; } if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) { return; } Loading core/api/current.txt +1 −19 Original line number Diff line number Diff line Loading @@ -18053,24 +18053,6 @@ package android.graphics.pdf { method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } public final class PdfRenderer implements java.lang.AutoCloseable { ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException; method public void close(); method public int getPageCount(); method public android.graphics.pdf.PdfRenderer.Page openPage(int); method public boolean shouldScaleForPrinting(); } public final class PdfRenderer.Page implements java.lang.AutoCloseable { method public void close(); method public int getHeight(); method public int getIndex(); method public int getWidth(); method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int); field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 } } package android.graphics.text { Loading Loading @@ -56297,7 +56279,7 @@ package android.view.inputmethod { method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View); method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String); method @FlaggedApi("android.view.inputmethod.use_zero_jank_proxy") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int); method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent); method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]); method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo(); Loading
apex/jobscheduler/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ java_library { static_libs: [ "modules-utils-fastxmlserializer", "service-jobscheduler-alarm.flags-aconfig-java", "service-jobscheduler-job.flags-aconfig-java", ], Loading
apex/jobscheduler/service/aconfig/Android.bp +12 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,15 @@ java_aconfig_library { aconfig_declarations: "service-job.flags-aconfig", visibility: ["//frameworks/base:__subpackages__"], } // Alarm aconfig_declarations { name: "alarm_flags", package: "com.android.server.alarm", srcs: ["alarm.aconfig"], } java_aconfig_library { name: "service-jobscheduler-alarm.flags-aconfig-java", aconfig_declarations: "alarm_flags", }
apex/jobscheduler/service/aconfig/alarm.aconfig 0 → 100644 +11 −0 Original line number Diff line number Diff line package: "com.android.server.alarm" flag { name: "use_frozen_state_to_drop_listener_alarms" namespace: "backstage_power" description: "Use frozen state callback to drop listener alarms for cached apps" bug: "324470945" metadata { purpose: PURPOSE_BUGFIX } }
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +65 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.alarm; import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; Loading Loading @@ -75,6 +76,7 @@ import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AlarmManager; Loading Loading @@ -103,6 +105,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Looper; import android.os.Message; Loading Loading @@ -145,6 +148,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.LocalLog; Loading Loading @@ -293,6 +297,7 @@ public class AlarmManagerService extends SystemService { private final Injector mInjector; int mBroadcastRefCount = 0; boolean mUseFrozenStateToDropListenerAlarms; MetricsHelper mMetricsHelper; PowerManager.WakeLock mWakeLock; SparseIntArray mAlarmsPerUid = new SparseIntArray(); Loading Loading @@ -1856,15 +1861,47 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mHandler = new AlarmHandler(); mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithFgsForAlarmClock.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false); mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mMetricsHelper = new MetricsHelper(getContext(), mLock); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mUseFrozenStateToDropListenerAlarms = Flags.useFrozenStateToDropListenerAlarms(); if (mUseFrozenStateToDropListenerAlarms) { final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> { final int size = frozenStates.length; if (uids.length != size) { Slog.wtf(TAG, "Got different length arrays in frozen state callback!" + " uids.length: " + uids.length + " frozenStates.length: " + size); // Cannot process received data in any meaningful way. return; } final IntArray affectedUids = new IntArray(); for (int i = 0; i < size; i++) { if (frozenStates[i] != UID_FROZEN_STATE_FROZEN) { continue; } if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uids[i])) { continue; } affectedUids.add(uids[i]); } if (affectedUids.size() > 0) { removeExactListenerAlarms(affectedUids.toArray()); } }; final ActivityManager am = getContext().getSystemService(ActivityManager.class); am.registerUidFrozenStateChangedCallback(new HandlerExecutor(mHandler), callback); } mListenerDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { Loading @@ -1880,7 +1917,6 @@ public class AlarmManagerService extends SystemService { }; synchronized (mLock) { mHandler = new AlarmHandler(); mConstants = new Constants(mHandler); mAlarmStore = new LazyAlarmStore(); Loading Loading @@ -1960,6 +1996,21 @@ public class AlarmManagerService extends SystemService { publishBinderService(Context.ALARM_SERVICE, mService); } private void removeExactListenerAlarms(int... whichUids) { synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (!ArrayUtils.contains(whichUids, a.uid) || a.listener == null || a.windowLength != 0) { return false; } Slog.w(TAG, "Alarm " + a.listenerTag + " being removed for " + UserHandle.formatUid(a.uid) + ":" + a.packageName + " because the app got frozen"); return true; }, REMOVE_REASON_LISTENER_CACHED); } } void refreshExactAlarmCandidates() { final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages( Manifest.permission.SCHEDULE_EXACT_ALARM); Loading Loading @@ -3074,6 +3125,14 @@ public class AlarmManagerService extends SystemService { mConstants.dump(pw); pw.println(); pw.println("Feature Flags:"); pw.increaseIndent(); pw.print(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS, mUseFrozenStateToDropListenerAlarms); pw.decreaseIndent(); pw.println(); pw.println(); if (mConstants.USE_TARE_POLICY == EconomyManager.ENABLED_MODE_ON) { pw.println("TARE details:"); pw.increaseIndent(); Loading Loading @@ -4959,18 +5018,7 @@ public class AlarmManagerService extends SystemService { break; case REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED: uid = (Integer) msg.obj; synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (a.uid != uid || a.listener == null || a.windowLength != 0) { return false; } // TODO (b/265195908): Change to .w once we have some data on breakages. Slog.wtf(TAG, "Alarm " + a.listenerTag + " being removed for " + UserHandle.formatUid(a.uid) + ":" + a.packageName + " because the app went into cached state"); return true; }, REMOVE_REASON_LISTENER_CACHED); } removeExactListenerAlarms(uid); break; default: // nope, just ignore it Loading Loading @@ -5322,6 +5370,10 @@ public class AlarmManagerService extends SystemService { @Override public void handleUidCachedChanged(int uid, boolean cached) { if (mUseFrozenStateToDropListenerAlarms) { // Use ActivityManager#UidFrozenStateChangedCallback instead. return; } if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) { return; } Loading
core/api/current.txt +1 −19 Original line number Diff line number Diff line Loading @@ -18053,24 +18053,6 @@ package android.graphics.pdf { method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } public final class PdfRenderer implements java.lang.AutoCloseable { ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException; method public void close(); method public int getPageCount(); method public android.graphics.pdf.PdfRenderer.Page openPage(int); method public boolean shouldScaleForPrinting(); } public final class PdfRenderer.Page implements java.lang.AutoCloseable { method public void close(); method public int getHeight(); method public int getIndex(); method public int getWidth(); method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int); field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 } } package android.graphics.text { Loading Loading @@ -56297,7 +56279,7 @@ package android.view.inputmethod { method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View); method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String); method @FlaggedApi("android.view.inputmethod.use_zero_jank_proxy") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int); method @FlaggedApi("android.view.inputmethod.home_screen_handwriting_delegator") public void acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent); method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]); method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo();