diff options
12 files changed, 248 insertions, 49 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java index df751fc9fa48..180c77250fd1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java @@ -79,22 +79,23 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { } @Override - public void registerOrganizer() { - if (mAnimationController != null) { - throw new IllegalStateException("Must unregister the organizer before re-register."); + public void unregisterOrganizer() { + stopOverrideSplitAnimation(); + mAnimationController = null; + super.unregisterOrganizer(); + } + + void startOverrideSplitAnimation() { + if (mAnimationController == null) { + mAnimationController = new TaskFragmentAnimationController(this); } - super.registerOrganizer(); - mAnimationController = new TaskFragmentAnimationController(this); mAnimationController.registerRemoteAnimations(); } - @Override - public void unregisterOrganizer() { + void stopOverrideSplitAnimation() { if (mAnimationController != null) { mAnimationController.unregisterRemoteAnimations(); - mAnimationController = null; } - super.unregisterOrganizer(); } /** diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index b8e8b0114b47..8f368c2bee22 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -33,6 +33,7 @@ import android.app.Instrumentation; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -63,6 +64,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private @NonNull Consumer<List<SplitInfo>> mEmbeddingCallback; private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>(); + // We currently only support split activity embedding within the one root Task. + private final Rect mParentBounds = new Rect(); + public SplitController() { mPresenter = new SplitPresenter(new MainThreadExecutor(), this); ActivityThread activityThread = ActivityThread.currentActivityThread(); @@ -79,6 +83,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) { mSplitRules.clear(); mSplitRules.addAll(rules); + updateAnimationOverride(); } @NonNull @@ -158,6 +163,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) { + onParentBoundsMayChange(parentConfig.windowConfiguration.getBounds()); TaskFragmentContainer container = getContainer(fragmentToken); if (container != null) { mPresenter.updateContainer(container); @@ -165,6 +171,51 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } + private void onParentBoundsMayChange(Activity activity) { + if (activity.isFinishing()) { + return; + } + + onParentBoundsMayChange(mPresenter.getParentContainerBounds(activity)); + } + + private void onParentBoundsMayChange(Rect parentBounds) { + if (!parentBounds.isEmpty() && !mParentBounds.equals(parentBounds)) { + mParentBounds.set(parentBounds); + updateAnimationOverride(); + } + } + + /** + * Updates if we should override transition animation. We only want to override if the Task + * bounds is large enough for at least one split rule. + */ + private void updateAnimationOverride() { + if (mParentBounds.isEmpty()) { + // We don't know about the parent bounds yet. + return; + } + + // Check if the parent container bounds can support any split rule. + boolean supportSplit = false; + for (EmbeddingRule rule : mSplitRules) { + if (!(rule instanceof SplitRule)) { + continue; + } + if (mPresenter.shouldShowSideBySide(mParentBounds, (SplitRule) rule)) { + supportSplit = true; + break; + } + } + + // We only want to override if it supports split. + if (supportSplit) { + mPresenter.startOverrideSplitAnimation(); + } else { + mPresenter.stopOverrideSplitAnimation(); + } + } + void onActivityCreated(@NonNull Activity launchedActivity) { handleActivityCreated(launchedActivity); updateCallbackIfNecessary(); @@ -180,6 +231,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen final TaskFragmentContainer currentContainer = getContainerWithActivity( launchedActivity.getActivityToken()); + if (currentContainer == null) { + // Initial check before any TaskFragment is created. + onParentBoundsMayChange(launchedActivity); + } + // Check if the activity is configured to always be expanded. if (shouldExpand(launchedActivity, null, splitRules)) { if (shouldContainerBeExpanded(currentContainer)) { @@ -257,6 +313,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // onTaskFragmentParentInfoChanged return; } + // The bounds of the container may have been changed. + onParentBoundsMayChange(activity); // Check if activity requires a placeholder launchPlaceholderIfNecessary(activity); @@ -346,7 +404,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen TaskFragmentContainer getTopActiveContainer() { for (int i = mContainers.size() - 1; i >= 0; i--) { TaskFragmentContainer container = mContainers.get(i); - if (!container.isFinished()) { + if (!container.isFinished() && container.getTopNonFinishingActivity() != null) { return container; } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java index 3c7d2de6165f..a801dc8193fd 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java @@ -37,32 +37,42 @@ class TaskFragmentAnimationController { private final TaskFragmentOrganizer mOrganizer; private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner(); + private final RemoteAnimationDefinition mDefinition; + private boolean mIsRegister; TaskFragmentAnimationController(TaskFragmentOrganizer organizer) { mOrganizer = organizer; + mDefinition = new RemoteAnimationDefinition(); + final RemoteAnimationAdapter animationAdapter = + new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */); + mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter); + mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter); } void registerRemoteAnimations() { if (DEBUG) { Log.v(TAG, "registerRemoteAnimations"); } - final RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); - final RemoteAnimationAdapter animationAdapter = - new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */); - definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter); - definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter); - mOrganizer.registerRemoteAnimations(definition); + if (mIsRegister) { + return; + } + mOrganizer.registerRemoteAnimations(mDefinition); + mIsRegister = true; } void unregisterRemoteAnimations() { if (DEBUG) { Log.v(TAG, "unregisterRemoteAnimations"); } + if (!mIsRegister) { + return; + } mOrganizer.unregisterRemoteAnimations(); + mIsRegister = false; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 7decb54d16bb..338c944f7eec 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -292,7 +292,6 @@ public class RecentTasksController implements TaskStackListenerCallback, * Invalidates this instance, preventing future calls from updating the controller. */ void invalidate() { - Slog.d("b/206648922", "invalidating controller: " + mController); mController = null; } @@ -313,13 +312,16 @@ public class RecentTasksController implements TaskStackListenerCallback, @Override public GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId) throws RemoteException { + if (mController == null) { + // The controller is already invalidated -- just return an empty task list for now + return new GroupedRecentTaskInfo[0]; + } + final GroupedRecentTaskInfo[][] out = new GroupedRecentTaskInfo[][]{null}; executeRemoteCallWithTaskPermission(mController, "getRecentTasks", (controller) -> out[0] = controller.getRecentTasks(maxNum, flags, userId) .toArray(new GroupedRecentTaskInfo[0]), true /* blocking */); - Slog.d("b/206648922", "getRecentTasks(" + maxNum + "): " + out[0] - + " mController=" + mController); return out[0]; } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt index 977e46ac3b44..d2ded71487dc 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt @@ -131,6 +131,12 @@ class ControlsProviderLifecycleManager( wrapper = null bindService(false) } + + override fun onNullBinding(name: ComponentName?) { + if (DEBUG) Log.d(TAG, "onNullBinding $name") + wrapper = null + context.unbindService(this) + } } private fun handlePendingServiceMethods() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt index 4de78f5d6190..868efa027f40 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt @@ -34,7 +34,7 @@ class LSShadeTransitionLogger @Inject constructor( private val displayMetrics: DisplayMetrics ) { fun logUnSuccessfulDragDown(startingChild: View?) { - val entry = (startingChild as ExpandableNotificationRow?)?.entry + val entry = (startingChild as? ExpandableNotificationRow)?.entry buffer.log(TAG, LogLevel.INFO, { str1 = entry?.key ?: "no entry" }, { @@ -49,7 +49,7 @@ class LSShadeTransitionLogger @Inject constructor( } fun logDragDownStarted(startingChild: ExpandableView?) { - val entry = (startingChild as ExpandableNotificationRow?)?.entry + val entry = (startingChild as? ExpandableNotificationRow)?.entry buffer.log(TAG, LogLevel.INFO, { str1 = entry?.key ?: "no entry" }, { @@ -58,7 +58,7 @@ class LSShadeTransitionLogger @Inject constructor( } fun logDraggedDownLockDownShade(startingChild: View?) { - val entry = (startingChild as ExpandableNotificationRow?)?.entry + val entry = (startingChild as? ExpandableNotificationRow)?.entry buffer.log(TAG, LogLevel.INFO, { str1 = entry?.key ?: "no entry" }, { @@ -67,7 +67,7 @@ class LSShadeTransitionLogger @Inject constructor( } fun logDraggedDown(startingChild: View?, dragLengthY: Int) { - val entry = (startingChild as ExpandableNotificationRow?)?.entry + val entry = (startingChild as? ExpandableNotificationRow)?.entry buffer.log(TAG, LogLevel.INFO, { str1 = entry?.key ?: "no entry" }, { diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt index 2d3757c29ebf..12096bc06748 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt @@ -17,6 +17,9 @@ package com.android.systemui.controls.controller import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection import android.os.UserHandle import android.service.controls.IControlsActionCallback import android.service.controls.IControlsProvider @@ -43,6 +46,8 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -57,8 +62,6 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { private lateinit var subscriberService: IControlsSubscriber.Stub @Mock private lateinit var service: IControlsProvider.Stub - @Mock - private lateinit var loadCallback: ControlsBindingController.LoadCallback @Captor private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper> @@ -75,7 +78,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - mContext.addMockService(componentName, service) + context.addMockService(componentName, service) executor = FakeExecutor(FakeSystemClock()) `when`(service.asBinder()).thenCallRealMethod() `when`(service.queryLocalInterface(ArgumentMatchers.anyString())).thenReturn(service) @@ -98,7 +101,36 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { fun testBindService() { manager.bindService() executor.runAllReady() - assertTrue(mContext.isBound(componentName)) + assertTrue(context.isBound(componentName)) + } + + @Test + fun testNullBinding() { + val mockContext = mock(Context::class.java) + lateinit var serviceConnection: ServiceConnection + `when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer { + val component = (it.arguments[0] as Intent).component + if (component == componentName) { + serviceConnection = it.arguments[1] as ServiceConnection + serviceConnection.onNullBinding(component) + true + } else { + false + } + } + + val nullManager = ControlsProviderLifecycleManager( + mockContext, + executor, + actionCallbackService, + UserHandle.of(0), + componentName + ) + + nullManager.bindService() + executor.runAllReady() + + verify(mockContext).unbindService(serviceConnection) } @Test @@ -109,7 +141,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { manager.unbindService() executor.runAllReady() - assertFalse(mContext.isBound(componentName)) + assertFalse(context.isBound(componentName)) } @Test @@ -119,7 +151,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { verify(service).load(subscriberService) - assertTrue(mContext.isBound(componentName)) + assertTrue(context.isBound(componentName)) } @Test @@ -129,7 +161,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { manager.unbindService() executor.runAllReady() - assertFalse(mContext.isBound(componentName)) + assertFalse(context.isBound(componentName)) } @Test @@ -162,7 +194,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { manager.maybeBindAndSubscribe(list, subscriberService) executor.runAllReady() - assertTrue(mContext.isBound(componentName)) + assertTrue(context.isBound(componentName)) verify(service).subscribe(list, subscriberService) } @@ -173,7 +205,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { manager.maybeBindAndSendAction(controlId, action) executor.runAllReady() - assertTrue(mContext.isBound(componentName)) + assertTrue(context.isBound(componentName)) verify(service).action(eq(controlId), capture(wrapperCaptor), eq(actionCallbackService)) assertEquals(action, wrapperCaptor.getValue().getWrappedAction()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt new file mode 100644 index 000000000000..6971c63ed6d4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt @@ -0,0 +1,44 @@ +package com.android.systemui.statusbar + +import android.testing.AndroidTestingRunner +import android.util.DisplayMetrics +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.log.LogBuffer +import com.android.systemui.statusbar.notification.row.ExpandableView +import com.android.systemui.statusbar.phone.LSShadeTransitionLogger +import com.android.systemui.statusbar.phone.LockscreenGestureLogger +import com.android.systemui.util.mockito.mock +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class LSShadeTransitionLoggerTest : SysuiTestCase() { + lateinit var logger: LSShadeTransitionLogger + @Mock + lateinit var gestureLogger: LockscreenGestureLogger + @Mock + lateinit var displayMetrics: DisplayMetrics + @JvmField @Rule + val mockito = MockitoJUnit.rule() + + @Before + fun setup() { + logger = LSShadeTransitionLogger( + LogBuffer("Test", 10, 10, mock()), + gestureLogger, + displayMetrics) + } + + @Test + fun testLogDragDownStarted() { + val view: ExpandableView = mock() + // log a non-null, non row, ensure no crash + logger.logDragDownStarted(view) + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 8199d940883a..6bb5aa148e59 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -523,6 +523,8 @@ public final class CachedAppOptimizer { */ static private native void compactProcess(int pid, int compactionFlags); + static private native void cancelCompaction(); + /** * Reads the flag value from DeviceConfig to determine whether app compaction * should be enabled, and starts the freeze/compaction thread if needed. @@ -1026,6 +1028,26 @@ public final class CachedAppOptimizer { } } + @GuardedBy({"mService", "mProcLock"}) + void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) { + // Cancel any currently executing compactions + // if the process moved out of cached state + if (DefaultProcessDependencies.mPidCompacting == app.mPid && newAdj < oldAdj + && newAdj < ProcessList.CACHED_APP_MIN_ADJ) { + cancelCompaction(); + } + + // Perform a minor compaction when a perceptible app becomes the prev/home app + // Perform a major compaction when any app enters cached + if (oldAdj <= ProcessList.PERCEPTIBLE_APP_ADJ + && (newAdj == ProcessList.PREVIOUS_APP_ADJ || newAdj == ProcessList.HOME_APP_ADJ)) { + compactAppSome(app); + } else if (newAdj >= ProcessList.CACHED_APP_MIN_ADJ + && newAdj <= ProcessList.CACHED_APP_MAX_ADJ) { + compactAppFull(app); + } + } + @VisibleForTesting static final class LastCompactionStats { private final long[] mRssAfterCompaction; @@ -1068,6 +1090,13 @@ public final class CachedAppOptimizer { name = proc.processName; opt.setHasPendingCompact(false); + if (mAm.mInternal.isPendingTopUid(proc.uid)) { + // In case the OOM Adjust has not yet been propagated we see if this is + // pending on becoming top app in which case we should not compact. + Slog.e(TAG_AM, "Skip compaction since UID is active for " + name); + return; + } + // don't compact if the process has returned to perceptible // and this is only a cached/home/prev compaction if ((pendingAction == COMPACT_PROCESS_SOME @@ -1477,6 +1506,8 @@ public final class CachedAppOptimizer { * Default implementation for ProcessDependencies, public vor visibility to OomAdjuster class. */ private static final class DefaultProcessDependencies implements ProcessDependencies { + public static int mPidCompacting = -1; + // Get memory RSS from process. @Override public long[] getRss(int pid) { @@ -1486,6 +1517,7 @@ public final class CachedAppOptimizer { // Compact process. @Override public void performCompaction(String action, int pid) throws IOException { + mPidCompacting = pid; if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])) { compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG); } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FILE])) { @@ -1493,6 +1525,7 @@ public final class CachedAppOptimizer { } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) { compactProcess(pid, COMPACT_ACTION_ANON_FLAG); } + mPidCompacting = -1; } } } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 7673123c6476..88ca8a5e8356 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2606,18 +2606,9 @@ public class OomAdjuster { // don't compact during bootup if (mCachedAppOptimizer.useCompaction() && mService.mBooted) { // Cached and prev/home compaction + // reminder: here, setAdj is previous state, curAdj is upcoming state if (state.getCurAdj() != state.getSetAdj()) { - // Perform a minor compaction when a perceptible app becomes the prev/home app - // Perform a major compaction when any app enters cached - // reminder: here, setAdj is previous state, curAdj is upcoming state - if (state.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ - && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ - || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) { - mCachedAppOptimizer.compactAppSome(app); - } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ - && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) { - mCachedAppOptimizer.compactAppFull(app); - } + mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app); } else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE && state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ // Because these can fire independent of oom_adj/procstate changes, we need diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 7cf60e8fedb2..2e02e4977094 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -8422,7 +8422,7 @@ public class AudioService extends IAudioService.Stub /** @see Spatializer#getSpatializerCompatibleAudioDevices() */ public @NonNull List<AudioDeviceAttributes> getSpatializerCompatibleAudioDevices() { - enforceModifyAudioRoutingPermission(); + enforceModifyDefaultAudioEffectsPermission(); return mSpatializerHelper.getCompatibleAudioDevices(); } diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp index 4190a91710fc..94bc22a05d7a 100644 --- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp +++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp @@ -59,6 +59,9 @@ using android::base::unique_fd; namespace android { +static bool cancelRunningCompaction; +static bool compactionInProgress; + // Legacy method for compacting processes, any new code should // use compactProcess instead. static inline void compactProcessProcfs(int pid, const std::string& compactionType) { @@ -83,9 +86,18 @@ static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseT // Skip compaction if failed to open pidfd with any error return -errno; } + compactionInProgress = true; + cancelRunningCompaction = false; int64_t totalBytesCompacted = 0; for (int iBase = 0; iBase < vmas.size(); iBase += UIO_MAXIOV) { + if (CC_UNLIKELY(cancelRunningCompaction)) { + // There could be a significant delay betweenwhen a compaction + // is requested and when it is handled during this time + // our OOM adjust could have improved. + cancelRunningCompaction = false; + break; + } int totalVmasToKernel = std::min(UIO_MAXIOV, (int)(vmas.size() - iBase)); for (int iVec = 0, iVma = iBase; iVec < totalVmasToKernel; ++iVec, ++iVma) { vmasToKernel[iVec].iov_base = (void*)vmas[iVma].start; @@ -95,11 +107,13 @@ static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseT auto bytesCompacted = process_madvise(pidfd, vmasToKernel, totalVmasToKernel, madviseType, 0); if (CC_UNLIKELY(bytesCompacted == -1)) { + compactionInProgress = false; return -errno; } totalBytesCompacted += bytesCompacted; } + compactionInProgress = false; return totalBytesCompacted; } @@ -228,6 +242,12 @@ static void com_android_server_am_CachedAppOptimizer_compactSystem(JNIEnv *, job } } +static void com_android_server_am_CachedAppOptimizer_cancelCompaction(JNIEnv*, jobject) { + if (compactionInProgress) { + cancelRunningCompaction = true; + } +} + static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, jobject, jint pid, jint compactionFlags) { compactProcessOrFallback(pid, compactionFlags); @@ -279,6 +299,8 @@ static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIE static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ + {"cancelCompaction", "()V", + (void*)com_android_server_am_CachedAppOptimizer_cancelCompaction}, {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem}, {"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess}, {"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder}, |