diff options
13 files changed, 153 insertions, 36 deletions
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 7615b87c7102..6d49add65c5b 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -825,6 +825,7 @@ public class CameraDeviceImpl extends CameraDevice if (surface == null) throw new IllegalArgumentException("Surface is null"); synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); int streamId = -1; for (int i = 0; i < mConfiguredOutputs.size(); i++) { final List<Surface> surfaces = mConfiguredOutputs.valueAt(i).getSurfaces(); @@ -847,6 +848,7 @@ public class CameraDeviceImpl extends CameraDevice maxCount); synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); int streamId = -1; for (int i = 0; i < mConfiguredOutputs.size(); i++) { if (surface == mConfiguredOutputs.valueAt(i).getSurface()) { @@ -865,6 +867,7 @@ public class CameraDeviceImpl extends CameraDevice public void updateOutputConfiguration(OutputConfiguration config) throws CameraAccessException { synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); int streamId = -1; for (int i = 0; i < mConfiguredOutputs.size(); i++) { if (config.getSurface() == mConfiguredOutputs.valueAt(i).getSurface()) { @@ -895,6 +898,7 @@ public class CameraDeviceImpl extends CameraDevice CameraOfflineSession ret; synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); if (mOfflineSessionImpl != null) { throw new IllegalStateException("Switch to offline mode already in progress"); } @@ -987,6 +991,7 @@ public class CameraDeviceImpl extends CameraDevice if (surface == null) throw new IllegalArgumentException("Surface is null"); synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); int streamId = -1; for (int i = 0; i < mConfiguredOutputs.size(); i++) { if (surface == mConfiguredOutputs.valueAt(i).getSurface()) { @@ -1009,6 +1014,8 @@ public class CameraDeviceImpl extends CameraDevice } synchronized(mInterfaceLock) { + checkIfCameraClosedOrInError(); + for (OutputConfiguration config : outputConfigs) { int streamId = -1; for (int i = 0; i < mConfiguredOutputs.size(); i++) { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 5790150a3425..941437998838 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -789,9 +789,11 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, xform[i - start].fTx = pos.x() - tan.y() * y - halfWidth * tan.x(); xform[i - start].fTy = pos.y() + tan.x() * y - halfWidth * tan.y(); } - auto* finalCanvas = this->asSkCanvas(); + + sk_sp<SkTextBlob> textBlob(builder.make()); + apply_looper(&paintCopy, [&](const SkPaint& p) { - finalCanvas->drawTextBlob(builder.make(), 0, 0, paintCopy); + mCanvas->drawTextBlob(textBlob, 0, 0, p); }); } diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index c19b1878ad45..335bcdcfc1fb 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -440,6 +440,12 @@ void CanvasContext::draw() { if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) { mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame); + // Notify the callbacks, even if there's nothing to draw so they aren't waiting + // indefinitely + for (auto& func : mFrameCompleteCallbacks) { + std::invoke(func, mFrameNumber); + } + mFrameCompleteCallbacks.clear(); return; } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 9b4aebcd8aff..412b43e6a582 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1993,7 +1993,7 @@ public class LocationManager { @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull GnssStatus.Callback callback) { - return registerGnssStatusCallback(Runnable::run, callback); + return registerGnssStatusCallback(callback, null); } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 7295f327d47a..8ce3f005cea7 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -190,6 +190,7 @@ public class PipTaskOrganizer extends TaskOrganizer { private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; + private PictureInPictureParams mPictureInPictureParams; public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler, @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper, @@ -257,8 +258,9 @@ public class PipTaskOrganizer extends TaskOrganizer { @Override public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) { Objects.requireNonNull(info, "Requires RunningTaskInfo"); + mPictureInPictureParams = info.pictureInPictureParams; final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds( - info.topActivity, getAspectRatioOrDefault(info.pictureInPictureParams), + info.topActivity, getAspectRatioOrDefault(mPictureInPictureParams), null /* bounds */, getMinimalSize(info.topActivityInfo)); Objects.requireNonNull(destinationBounds, "Missing destination bounds"); mTaskInfo = info; @@ -304,6 +306,7 @@ public class PipTaskOrganizer extends TaskOrganizer { Log.wtf(TAG, "Unrecognized token: " + token); return; } + mPictureInPictureParams = null; mInPip = false; } @@ -311,7 +314,7 @@ public class PipTaskOrganizer extends TaskOrganizer { public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken"); final PictureInPictureParams newParams = info.pictureInPictureParams; - if (!shouldUpdateDestinationBounds(newParams)) { + if (!applyPictureInPictureParams(newParams)) { Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams); return; } @@ -359,7 +362,7 @@ public class PipTaskOrganizer extends TaskOrganizer { } final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds( - mTaskInfo.topActivity, getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams), + mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams), null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo)); if (newDestinationBounds.equals(currentDestinationBounds)) return; if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) { @@ -373,12 +376,14 @@ public class PipTaskOrganizer extends TaskOrganizer { * @return {@code true} if the aspect ratio is changed since no other parameters within * {@link PictureInPictureParams} would affect the bounds. */ - private boolean shouldUpdateDestinationBounds(PictureInPictureParams params) { - if (params == null || mTaskInfo.pictureInPictureParams == null) { - return params != mTaskInfo.pictureInPictureParams; + private boolean applyPictureInPictureParams(@NonNull PictureInPictureParams params) { + final boolean changed = (mPictureInPictureParams == null) ? true : !Objects.equals( + mPictureInPictureParams.getAspectRatioRational(), params.getAspectRatioRational()); + if (changed) { + mPictureInPictureParams = params; + mPipBoundsHandler.onAspectRatioChanged(params.getAspectRatio()); } - return !Objects.equals(mTaskInfo.pictureInPictureParams.getAspectRatioRational(), - params.getAspectRatioRational()); + return changed; } /** diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index d007b77c3203..5470b9c8c041 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5960,13 +5960,15 @@ public class NotificationManagerService extends SystemService { } } - // limit the number of outstanding notificationrecords an app can have - int count = getNotificationCountLocked(pkg, userId, id, tag); - if (count >= MAX_PACKAGE_NOTIFICATIONS) { - mUsageStats.registerOverCountQuota(pkg); - Slog.e(TAG, "Package has already posted or enqueued " + count - + " notifications. Not showing more. package=" + pkg); - return false; + // limit the number of non-fgs outstanding notificationrecords an app can have + if (!r.getNotification().isForegroundService()) { + int count = getNotificationCountLocked(pkg, userId, id, tag); + if (count >= MAX_PACKAGE_NOTIFICATIONS) { + mUsageStats.registerOverCountQuota(pkg); + Slog.e(TAG, "Package has already posted or enqueued " + count + + " notifications. Not showing more. package=" + pkg); + return false; + } } } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5df84f299509..5f8e9ffb2881 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1192,8 +1192,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final Configuration newConfig = new Configuration(); newConfig.setTo(task.getRequestedOverrideConfiguration()); Rect outBounds = newConfig.windowConfiguration.getBounds(); - task.adjustForMinimalTaskDimensions(outBounds, outBounds); - task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration()); + final Configuration parentConfig = task.getParent().getConfiguration(); + task.adjustForMinimalTaskDimensions(outBounds, outBounds, parentConfig); + task.computeConfigResourceOverrides(newConfig, parentConfig); } Task getTask() { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 6c872a6319d7..7d7e6aa0d0a9 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1822,22 +1822,16 @@ class Task extends WindowContainer<WindowContainer> { } } - void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) { - final Rect parentBounds = getParent() != null ? getParent().getBounds() : null; - if (bounds == null - || (bounds.isEmpty() && (parentBounds == null || parentBounds.isEmpty()))) { - return; - } + void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds, + @NonNull Configuration parentConfig) { int minWidth = mMinWidth; int minHeight = mMinHeight; // If the task has no requested minimal size, we'd like to enforce a minimal size // so that the user can not render the task too small to manipulate. We don't need // to do this for the pinned stack as the bounds are controlled by the system. - if (!inPinnedWindowingMode() && getStack() != null) { + if (!inPinnedWindowingMode()) { final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp; - final DisplayContent display = getDisplayContent(); - final float density = - (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT; + final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT; final int defaultMinSize = (int) (defaultMinSizeDp * density); if (minWidth == INVALID_MIN_SIZE) { @@ -1850,6 +1844,7 @@ class Task extends WindowContainer<WindowContainer> { if (bounds.isEmpty()) { // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they // do, we can just skip. + final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) { return; } @@ -2444,12 +2439,13 @@ class Task extends WindowContainer<WindowContainer> { } if (isLeafTask()) { - resolveLeafOnlyOverrideConfigs(newParentConfig); + resolveLeafOnlyOverrideConfigs(newParentConfig, mTmpBounds /* previousBounds */); } computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig); } - void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig) { + private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig, + Rect previousBounds) { int windowingMode = getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode(); if (windowingMode == WINDOWING_MODE_UNDEFINED) { @@ -2462,9 +2458,12 @@ class Task extends WindowContainer<WindowContainer> { computeFullscreenBounds(outOverrideBounds, null /* refActivity */, newParentConfig.windowConfiguration.getBounds(), newParentConfig.orientation); + // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if + // the parent or display is smaller than the size, the content may be cropped. + return; } - adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds); + adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig); if (windowingMode == WINDOWING_MODE_FREEFORM) { // by policy, make sure the window remains within parent somewhere final float density = diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java index e5486473e93b..0e48e7ed2682 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java @@ -70,8 +70,12 @@ public class UriGrantsManagerServiceTest { mLocalService = mService.getLocalService(); } + /** + * Verify that a camera sharing a normally-private photo with a social media + * app in the same user issues a grant. + */ @Test - public void testNeeded_normal() { + public void testNeeded_normal_sameUser() { final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ); @@ -85,6 +89,24 @@ public class UriGrantsManagerServiceTest { } /** + * Verify that a camera sharing a normally-private photo with a social media + * app in a different user issues a grant. + */ + @Test + public void testNeeded_normal_differentUser() { + final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); + final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ); + + final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( + UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null, + USER_SECONDARY); + assertEquals(PKG_SOCIAL, needed.targetPkg); + assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid); + assertEquals(FLAG_READ, needed.flags); + assertEquals(asSet(expectedGrant), needed.uris); + } + + /** * No need to issue grants for public authorities. */ @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index e644f64cf307..bda0c610fa12 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -6652,4 +6652,62 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertFalse(mBinderService.hasSentMessage(PKG, mUid)); } + + @Test + public void testCanPostFgsWhenOverLimit() throws RemoteException { + for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { + StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, + i, null, false).getSbn(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCanPostFgsWhenOverLimit", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + } + + final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); + sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCanPostFgsWhenOverLimit - fgs over limit!", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + + waitForIdle(); + + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(sbn.getPackageName()); + assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); + assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, + mService.getNotificationRecordCount()); + } + + @Test + public void testCannotPostNonFgsWhenOverLimit() throws RemoteException { + for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) { + StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, + i, null, false).getSbn(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCanPostFgsWhenOverLimit", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + } + + final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, + 100, null, false).getSbn(); + sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCanPostFgsWhenOverLimit - fgs over limit!", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + + final StatusBarNotification sbn2 = generateNotificationRecord(mTestNotificationChannel, + 101, null, false).getSbn(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCanPostFgsWhenOverLimit - non fgs over limit!", + sbn2.getId(), sbn2.getNotification(), sbn2.getUserId()); + + waitForIdle(); + + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(sbn.getPackageName()); + assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, notifs.length); + assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1, + mService.getNotificationRecordCount()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index 60875de5a68b..f0a97c5f9d6a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -448,6 +448,21 @@ public class TaskRecordTests extends ActivityTestsBase { } @Test + public void testFullScreenTaskNotAdjustedByMinimalSize() { + final Task fullscreenTask = new TaskBuilder(mSupervisor).build(); + final Rect originalTaskBounds = new Rect(fullscreenTask.getBounds()); + final ActivityInfo aInfo = new ActivityInfo(); + aInfo.windowLayout = new ActivityInfo.WindowLayout(0 /* width */, 0 /* widthFraction */, + 0 /* height */, 0 /* heightFraction */, 0 /* gravity */, + originalTaskBounds.width() * 2 /* minWidth */, + originalTaskBounds.height() * 2 /* minHeight */); + fullscreenTask.setMinDimensions(aInfo); + fullscreenTask.onConfigurationChanged(fullscreenTask.getParent().getConfiguration()); + + assertEquals(originalTaskBounds, fullscreenTask.getBounds()); + } + + @Test public void testInsetDisregardedWhenFreeformOverlapsNavBar() { TaskDisplayArea taskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea(); ActivityStack stack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java index 9fdb9d8f9844..d65b084ca8c1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java @@ -204,7 +204,7 @@ public class TaskStackTests extends WindowTestsBase { .when(windowConfiguration).getWindowingMode(); // Prevent adjust task dimensions - doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any()); + doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any()); final Rect stackBounds = new Rect(200, 200, 800, 1000); // Update surface position and size by the given bounds. diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index aa68c6900f6f..2ea58a028a0a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -507,7 +507,7 @@ public class WindowOrganizerTests extends WindowTestsBase { Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask(); Configuration c = new Configuration(task1.getRequestedOverrideConfiguration()); c.windowConfiguration.setBounds(newSize); - doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any()); + doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any()); task1.onRequestedOverrideConfigurationChanged(c); assertEquals(newSize, stack.getBounds()); |