Merge "Set shelf screenshot landscape size and window insets" into 24D1-dev
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 8e73379..ae10bef 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -415,7 +415,7 @@
}
flag {
- name: "screenshot_shelf_ui"
+ name: "screenshot_shelf_ui2"
namespace: "systemui"
description: "Use new shelf UI flow for screenshots"
bug: "329659738"
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
index afb0280..d1b08f1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ReferenceScreenshotModule.java
@@ -35,4 +35,10 @@
@Binds
ScreenshotActionsProvider.Factory bindScreenshotActionsProviderFactory(
DefaultScreenshotActionsProvider.Factory defaultScreenshotActionsProviderFactory);
+
+ /** */
+ @Provides
+ static ThumbnailObserver providesThumbnailObserver() {
+ return new ThumbnailObserver();
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 3207db9..0217fc2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -19,7 +19,7 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
@@ -403,7 +403,7 @@
return;
}
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
final UUID requestId = UUID.randomUUID();
final String screenshotId = String.format("Screenshot_%s", requestId);
mActionsProvider = mActionsProviderFactory.create(
@@ -454,7 +454,7 @@
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
- if (!screenshotShelfUi()) {
+ if (!screenshotShelfUi2()) {
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
}
@@ -503,7 +503,7 @@
}
boolean isPendingSharedTransition() {
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
return mActionExecutor.isPendingSharedTransition();
} else {
return mViewProxy.isPendingSharedTransition();
@@ -624,7 +624,7 @@
(response) -> {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION,
0, response.getPackageName());
- if (screenshotShelfUi() && mActionsProvider != null) {
+ if (screenshotShelfUi2() && mActionsProvider != null) {
mActionsProvider.onScrollChipReady(
() -> onScrollButtonClicked(owner, response));
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 3d72bca..9b754f3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -32,6 +32,7 @@
import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
import androidx.core.animation.doOnEnd
+import androidx.core.animation.doOnStart
import com.android.internal.logging.UiEventLogger
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.res.R
@@ -56,6 +57,7 @@
private val logger: UiEventLogger,
private val viewModel: ScreenshotViewModel,
private val windowManager: WindowManager,
+ private val thumbnailObserver: ThumbnailObserver,
@Assisted private val context: Context,
@Assisted private val displayId: Int
) : ScreenshotViewProxy {
@@ -100,6 +102,10 @@
info.touchableRegion.set(touchableRegion)
}
screenshotPreview = view.screenshotPreview
+ thumbnailObserver.setViews(
+ view.screenshotPreview,
+ view.requireViewById(R.id.screenshot_preview_border)
+ )
}
override fun reset() {
@@ -114,8 +120,12 @@
override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
val entrance = animationController.getEntranceAnimation(screenRect, showFlash)
- // reset the timeout when animation finishes
- entrance.doOnEnd { callbacks?.onUserInteraction() }
+ entrance.doOnStart { thumbnailObserver.onEntranceStarted() }
+ entrance.doOnEnd {
+ // reset the timeout when animation finishes
+ callbacks?.onUserInteraction()
+ thumbnailObserver.onEntranceComplete()
+ }
return entrance
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt
new file mode 100644
index 0000000..cf62a14
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ThumbnailObserver.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.view.View
+import android.widget.ImageView
+
+/** An observer of thumbnail UI and entrance state that can be overridden if needed. */
+open class ThumbnailObserver {
+ /** Thumbnail image and border views. */
+ open fun setViews(image: ImageView, border: View) {}
+
+ /** Entrance animation has begun. */
+ open fun onEntranceStarted() {}
+
+ /** Entrance animation has completed/stopped. */
+ open fun onEntranceComplete() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index b3eaa91..dbb3cb6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -16,7 +16,7 @@
package com.android.systemui.screenshot.dagger;
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
import android.app.Service;
import android.view.accessibility.AccessibilityManager;
@@ -102,7 +102,7 @@
static ScreenshotViewProxy.Factory providesScreenshotViewProxyFactory(
ScreenshotShelfViewProxy.Factory shelfScreenshotViewProxyFactory,
LegacyScreenshotViewProxy.Factory legacyScreenshotViewProxyFactory) {
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
return shelfScreenshotViewProxyFactory;
} else {
return legacyScreenshotViewProxyFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
index d642b7d..4eceb17 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
@@ -156,6 +156,12 @@
val previewAnimator = AnimatorSet()
previewAnimator.play(previewXAndScaleAnimator).with(previewYAnimator)
+ previewAnimator.doOnEnd {
+ screenshotPreview.scaleX = 1f
+ screenshotPreview.scaleY = 1f
+ screenshotPreview.x = endPos.x - screenshotPreview.width / 2f
+ screenshotPreview.y = endPos.y - screenshotPreview.height / 2f
+ }
previewAnimator.doOnStart { screenshotPreview.visibility = View.VISIBLE }
return previewAnimator
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 2d1aba4..b23628d 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2691,7 +2691,7 @@
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ && idMatchRelaxed(r, subId, phoneId)) {
try {
r.callback.onRadioPowerStateChanged(state);
} catch (RemoteException ex) {
@@ -4089,6 +4089,42 @@
}
}
+ /**
+ * Match the sub id or phone id of the event to the record with relaxed rules
+ *
+ * We follow the rules below:
+ * 1) If sub id of the event is invalid, phone id should be used.
+ * 2) If record's phoneId is also invalid then allow phone 0 notifications
+ * 3) The event on default sub should be notified to the records
+ * which register the default sub id.
+ * 4) Sub id should be exactly matched for all other cases.
+ * TODO: b/337878785 for longterm fix
+ */
+ boolean idMatchRelaxed(Record r, int subId, int phoneId) {
+
+ if (subId < 0) {
+ // Invalid case, we need compare phoneId.
+ // If the record does not have a valid phone Id send phone 0 notifications.
+ // A record's phoneId can get invalid if there is no SIM or modem was restarting
+ // when caller registered.
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ } else {
+ return (r.phoneId == phoneId);
+ }
+ }
+
+ if (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ // if the registered record does not have a valid phoneId then use the phone 0
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ }
+ return (subId == mDefaultSubId);
+ } else {
+ return (r.subId == subId);
+ }
+ }
+
private boolean checkFineLocationAccess(Record r) {
return checkFineLocationAccess(r, Build.VERSION_CODES.BASE);
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index cd96806..89c5a17 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -518,8 +518,17 @@
final SurfaceControl leash = mAdapter.mCapturedLeash;
mControlTarget = target;
updateVisibility();
+ boolean initiallyVisible = mClientVisible;
+ if (mSource.getType() == WindowInsets.Type.ime()) {
+ // The IME cannot be initially visible, see ControlAdapter#startAnimation below.
+ // Also, the ImeInsetsSourceConsumer clears the client visibility upon losing control,
+ // but this won't have reached here yet by the time the new control is created.
+ // Note: The DisplayImeController needs the correct previous client's visibility, so we
+ // only override the initiallyVisible here.
+ initiallyVisible = false;
+ }
mControl = new InsetsSourceControl(mSource.getId(), mSource.getType(), leash,
- mClientVisible, surfacePosition, getInsetsHint());
+ initiallyVisible, surfacePosition, getInsetsHint());
ProtoLog.d(WM_DEBUG_WINDOW_INSETS,
"InsetsSource Control %s for target %s", mControl, mControlTarget);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 21c16eb..606070c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4154,11 +4154,49 @@
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION})
+ public void testPortraitCloseToSquareDisplayWithTaskbar_insetsOverridden_notLetterboxed() {
+ // Set up portrait close to square display.
+ setUpDisplaySizeWithApp(2200, 2280);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ // Simulate insets, final app bounds are (0, 0, 2200, 2130) - landscape.
+ final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
+ "navbar");
+ final Binder owner = new Binder();
+ navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
+ .setInsetsSize(Insets.of(0, 0, 0, 150))
+ };
+ display.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
+ assertTrue(display.getDisplayPolicy().updateDecorInsetsInfo());
+ display.sendNewConfiguration();
+
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // Activity should not be letterboxed and should have portrait app bounds even though
+ // orientation is not respected with insets as insets have been decoupled.
+ final Rect appBounds = activity.getWindowConfiguration().getAppBounds();
+ final Rect displayBounds = display.getBounds();
+ assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertNotNull(appBounds);
+ assertEquals(displayBounds.width(), appBounds.width());
+ assertEquals(displayBounds.height(), appBounds.height());
+ }
+
+ @Test
@DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
public void testPortraitCloseToSquareDisplayWithTaskbar_letterboxed() {
// Set up portrait close to square display
setUpDisplaySizeWithApp(2200, 2280);
final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
// Simulate taskbar, final app bounds are (0, 0, 2200, 2130) - landscape
final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
"navbar");