diff options
321 files changed, 3450 insertions, 1605 deletions
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java index 452bb0ab5909..06207215b7be 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java @@ -19,6 +19,7 @@ package android.wm; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; +import android.graphics.Rect; import android.os.RemoteException; import android.os.SystemClock; import android.perftests.utils.ManualBenchmarkState; @@ -86,6 +87,7 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); final InsetsState mOutInsetsState = new InsetsState(); final InsetsSourceControl[] mOutControls = new InsetsSourceControl[0]; + final Rect mOutAttachedFrame = new Rect(); TestWindow() { mLayoutParams.setTitle(TestWindow.class.getName()); @@ -104,7 +106,7 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase long startTime = SystemClock.elapsedRealtimeNanos(); session.addToDisplay(this, mLayoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, mRequestedVisibilities, inputChannel, - mOutInsetsState, mOutControls); + mOutInsetsState, mOutControls, mOutAttachedFrame); final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime; state.addExtraResult("add", elapsedTimeNsOfAdd); diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java index 2fcab59cdec7..78214dc27a9f 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java @@ -385,6 +385,12 @@ public class PowerExemptionManager { */ public static final int REASON_ACTIVE_DEVICE_ADMIN = 324; + /** + * Media notification re-generate during transferring. + * @hide + */ + public static final int REASON_MEDIA_NOTIFICATION_TRANSFER = 325; + /** @hide The app requests out-out. */ public static final int REASON_OPT_OUT_REQUESTED = 1000; @@ -465,6 +471,7 @@ public class PowerExemptionManager { REASON_DPO_PROTECTED_APP, REASON_DISALLOW_APPS_CONTROL, REASON_ACTIVE_DEVICE_ADMIN, + REASON_MEDIA_NOTIFICATION_TRANSFER, }) @Retention(RetentionPolicy.SOURCE) public @interface ReasonCode {} @@ -830,6 +837,8 @@ public class PowerExemptionManager { return "ACTIVE_DEVICE_ADMIN"; case REASON_OPT_OUT_REQUESTED: return "REASON_OPT_OUT_REQUESTED"; + case REASON_MEDIA_NOTIFICATION_TRANSFER: + return "REASON_MEDIA_NOTIFICATION_TRANSFER"; default: return "(unknown:" + reasonCode + ")"; } diff --git a/boot/Android.bp b/boot/Android.bp index 5b265a5dc9de..3f14ebc4fd92 100644 --- a/boot/Android.bp +++ b/boot/Android.bp @@ -60,8 +60,8 @@ platform_bootclasspath { module: "art-bootclasspath-fragment", }, { - apex: "com.android.bluetooth", - module: "com.android.bluetooth-bootclasspath-fragment", + apex: "com.android.btservices", + module: "com.android.btservices-bootclasspath-fragment", }, { apex: "com.android.conscrypt", diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9e9e985d27de..546efaad85ac 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -274,11 +274,6 @@ public final class ActivityThread extends ClientTransactionHandler public static final boolean DEBUG_ORDER = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; /** - * If the activity doesn't become idle in time, the timeout will ensure to apply the pending top - * process state. - */ - private static final long PENDING_TOP_PROCESS_STATE_TIMEOUT = 1000; - /** * The delay to release the provider when it has no more references. It reduces the number of * transactions for acquiring and releasing provider if the client accesses the provider * frequently in a short time. @@ -367,8 +362,6 @@ public final class ActivityThread extends ClientTransactionHandler private final AtomicInteger mNumLaunchingActivities = new AtomicInteger(); @GuardedBy("mAppThread") private int mLastProcessState = PROCESS_STATE_UNKNOWN; - @GuardedBy("mAppThread") - private int mPendingProcessState = PROCESS_STATE_UNKNOWN; ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>(); private int mLastSessionId; final ArrayMap<IBinder, CreateServiceData> mServicesData = new ArrayMap<>(); @@ -2384,7 +2377,6 @@ public final class ActivityThread extends ClientTransactionHandler if (stopProfiling) { mProfiler.stopProfiling(); } - applyPendingProcessState(); return false; } } @@ -3438,16 +3430,7 @@ public final class ActivityThread extends ClientTransactionHandler return; } mLastProcessState = processState; - // Defer the top state for VM to avoid aggressive JIT compilation affecting activity - // launch time. - if (processState == ActivityManager.PROCESS_STATE_TOP - && mNumLaunchingActivities.get() > 0) { - mPendingProcessState = processState; - mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT); - } else { - mPendingProcessState = PROCESS_STATE_UNKNOWN; - updateVmProcessState(processState); - } + updateVmProcessState(processState); if (localLOGV) { Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState + (fromIpc ? " (from ipc" : "")); @@ -3465,20 +3448,6 @@ public final class ActivityThread extends ClientTransactionHandler VMRuntime.getRuntime().updateProcessState(state); } - private void applyPendingProcessState() { - synchronized (mAppThread) { - if (mPendingProcessState == PROCESS_STATE_UNKNOWN) { - return; - } - final int pendingState = mPendingProcessState; - mPendingProcessState = PROCESS_STATE_UNKNOWN; - // Only apply the pending state if the last state doesn't change. - if (pendingState == mLastProcessState) { - updateVmProcessState(pendingState); - } - } - } - @Override public void countLaunchingActivities(int num) { mNumLaunchingActivities.getAndAdd(num); @@ -5894,16 +5863,16 @@ public final class ActivityThread extends ClientTransactionHandler final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(), displayId); - final Configuration currentConfig = activity.mCurrentConfig; - final int diff = currentConfig.diffPublicOnly(newConfig); - final boolean hasPublicConfigChange = diff != 0; + final Configuration currentResConfig = activity.getResources().getConfiguration(); + final int diff = currentResConfig.diffPublicOnly(newConfig); + final boolean hasPublicResConfigChange = diff != 0; final ActivityClientRecord r = getActivityClient(activityToken); // TODO(b/173090263): Use diff instead after the improvement of AssetManager and // ResourcesImpl constructions. - final boolean shouldUpdateResources = hasPublicConfigChange - || shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig, - movedToDifferentDisplay, hasPublicConfigChange); - final boolean shouldReportChange = shouldReportChange(diff, currentConfig, newConfig, + final boolean shouldUpdateResources = hasPublicResConfigChange + || shouldUpdateResources(activityToken, currentResConfig, newConfig, + amOverrideConfig, movedToDifferentDisplay, hasPublicResConfigChange); + final boolean shouldReportChange = shouldReportChange(activity.mCurrentConfig, newConfig, r != null ? r.mSizeConfigurations : null, activity.mActivityInfo.getRealConfigChanged()); // Nothing significant, don't proceed with updating and reporting. @@ -5927,9 +5896,6 @@ public final class ActivityThread extends ClientTransactionHandler amOverrideConfig, contextThemeWrapperOverrideConfig); mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig, displayId); - activity.mConfigChangeFlags = 0; - activity.mCurrentConfig = new Configuration(newConfig); - // Apply the ContextThemeWrapper override if necessary. // NOTE: Make sure the configurations are not modified, as they are treated as immutable // in many places. @@ -5940,8 +5906,10 @@ public final class ActivityThread extends ClientTransactionHandler activity.dispatchMovedToDisplay(displayId, configToReport); } + activity.mConfigChangeFlags = 0; if (shouldReportChange) { activity.mCalled = false; + activity.mCurrentConfig = new Configuration(newConfig); activity.onConfigurationChanged(configToReport); if (!activity.mCalled) { throw new SuperNotCalledException("Activity " + activity.getLocalClassName() + @@ -5956,8 +5924,6 @@ public final class ActivityThread extends ClientTransactionHandler * Returns {@code true} if {@link Activity#onConfigurationChanged(Configuration)} should be * dispatched. * - * @param publicDiff Usually computed by {@link Configuration#diffPublicOnly(Configuration)}. - * This parameter is to prevent we compute it again. * @param currentConfig The current configuration cached in {@link Activity#mCurrentConfig}. * It is {@code null} before the first config update from the server side. * @param newConfig The updated {@link Configuration} @@ -5966,9 +5932,10 @@ public final class ActivityThread extends ClientTransactionHandler * @return {@code true} if the config change should be reported to the Activity */ @VisibleForTesting - public static boolean shouldReportChange(int publicDiff, @Nullable Configuration currentConfig, + public static boolean shouldReportChange(@Nullable Configuration currentConfig, @NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets, int handledConfigChanges) { + final int publicDiff = currentConfig.diffPublicOnly(newConfig); // Don't report the change if there's no public diff between current and new config. if (publicDiff == 0) { return false; diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 33cf71256d51..de0f7522f36d 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -1482,8 +1482,6 @@ public class Dialog implements DialogInterface, Window.Callback, /** * Returns the {@link OnBackInvokedDispatcher} instance associated with the window that this * dialog is attached to. - * - * Returns null if the dialog is not attached to a window with a decor. */ @NonNull public OnBackInvokedDispatcher getOnBackInvokedDispatcher() { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0e1a5461840e..34c91c360dbe 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -770,6 +770,10 @@ public class DevicePolicyManager { * <p>If this extra is set to {@code true}, the provisioning flow will still try to connect to * the internet, but if it fails it will start the offline provisioning flow. * + * <p>For T if this extra is set to {@code true}, the provisioning flow will be forced through + * the platform and there will be no attempt to download and install the device policy + * management role holder. + * * <p>The default value is {@code false}. * * <p>This extra is respected when provided via the provisioning intent actions such as {@link diff --git a/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java b/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java index 49992452df86..ca00154ab336 100644 --- a/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java +++ b/core/java/android/app/admin/FullyManagedDeviceProvisioningParams.java @@ -301,6 +301,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { * Sets a {@link PersistableBundle} that contains admin-specific extras. */ @NonNull + //TODO(b/235783053) The adminExtras parameter is actually @Nullable. public Builder setAdminExtras(@NonNull PersistableBundle adminExtras) { mAdminExtras = adminExtras != null ? new PersistableBundle(adminExtras) @@ -333,7 +334,7 @@ public final class FullyManagedDeviceProvisioningParams implements Parcelable { mLocalTime, mLocale, mDeviceOwnerCanGrantSensorsPermissions, - mAdminExtras, + mAdminExtras != null ? mAdminExtras : new PersistableBundle(), mDemoDevice); } } diff --git a/core/java/android/app/admin/ManagedProfileProvisioningParams.java b/core/java/android/app/admin/ManagedProfileProvisioningParams.java index f91d60a6a9fa..474f7859788b 100644 --- a/core/java/android/app/admin/ManagedProfileProvisioningParams.java +++ b/core/java/android/app/admin/ManagedProfileProvisioningParams.java @@ -252,6 +252,7 @@ public final class ManagedProfileProvisioningParams implements Parcelable { * Sets a {@link Bundle} that contains admin-specific extras. */ @NonNull + //TODO(b/235783053) The adminExtras parameter is actually @Nullable. public Builder setAdminExtras(@NonNull PersistableBundle adminExtras) { mAdminExtras = adminExtras != null ? new PersistableBundle(adminExtras) @@ -274,7 +275,7 @@ public final class ManagedProfileProvisioningParams implements Parcelable { mLeaveAllSystemAppsEnabled, mOrganizationOwnedProvisioning, mKeepingAccountOnMigration, - mAdminExtras); + mAdminExtras != null ? mAdminExtras : new PersistableBundle()); } } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 439c6396f1d0..608e34bd07b4 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -420,7 +420,10 @@ public class CompatibilityInfo implements Parcelable { * Translate a Rect in screen coordinates into the app window's coordinates. */ @UnsupportedAppUsage - public void translateRectInScreenToAppWindow(Rect rect) { + public void translateRectInScreenToAppWindow(@Nullable Rect rect) { + if (rect == null) { + return; + } rect.scale(applicationInvertedScale); } diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 73735edbb2ba..0f1b39c01289 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -892,9 +892,9 @@ public abstract class CameraDevice implements AutoCloseable { * <tr><th colspan="7">Preview stabilization guaranteed stream configurations</th></tr> * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr> * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr> - * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code RECORD}</td><td colspan="4" id="rb"></td> <td>Stabilized preview, GPU video processing, or no-preview stabilized video recording.</td> </tr> - * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr> - * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code RECORD }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr> + * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td><td colspan="4" id="rb"></td> <td>Stabilized preview, GPU video processing, or no-preview stabilized video recording.</td> </tr> + * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr> + * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr> * </table><br> * <p> * For the maximum size column, PREVIEW refers to the best size match to the device's screen diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java index a3bc66546a6a..e5b9cdb74d3b 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -1265,43 +1265,43 @@ public final class MandatoryStreamCombination { private static StreamCombinationTemplate sPreviewStabilizedStreamCombinations[] = { // 1 stream combinations new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD)}, + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p)}, "Stabilized preview, GPU video processing, or no-preview stabilized recording"), new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD)}, + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p)}, "Stabilized preview, GPU video processing, or no-preview stabilized recording"), //2 stream combinations new StreamCombinationTemplate(new StreamTemplate [] { new StreamTemplate(ImageFormat.JPEG, SizeThreshold.MAXIMUM), - new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p)}, "Standard JPEG still imaging with stabilized preview"), new StreamCombinationTemplate(new StreamTemplate [] { new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.MAXIMUM), - new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p)}, "Standard YUV still imaging with stabilized preview"), new StreamCombinationTemplate(new StreamTemplate [] { new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.MAXIMUM), - new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p)}, "Standard YUV still imaging with stabilized in-app image processing stream"), new StreamCombinationTemplate(new StreamTemplate [] { new StreamTemplate(ImageFormat.JPEG, SizeThreshold.MAXIMUM), - new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p)}, "Standard JPEG still imaging with stabilized in-app image processing stream"), new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p), new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, "High-resolution video recording with preview both streams stabilized"), new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p), new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, "High-resolution video recording with preview both streams stabilized"), new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p), new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.PREVIEW)}, "High-resolution video recording with preview both streams stabilized"), new StreamCombinationTemplate(new StreamTemplate [] { - new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.RECORD), + new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p), new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.PREVIEW)}, "High-resolution video recording with preview both streams stabilized"), }; @@ -1430,7 +1430,7 @@ public final class MandatoryStreamCombination { StreamCombinationTemplate []chosenStreamCombinations = sPreviewStabilizedStreamCombinations; - if (mIsPreviewStabilizationSupported) { + if (!mIsPreviewStabilizationSupported) { Log.v(TAG, "Device does not support preview stabilization"); return null; } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 334a659d7f23..8e67705c5cf0 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -135,6 +135,7 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import android.window.CompatOnBackInvokedCallback; import android.window.ImeOnBackInvokedDispatcher; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; @@ -350,7 +351,7 @@ public class InputMethodService extends AbstractInputMethodService { private RingBuffer<MotionEvent> mPendingEvents; private ImeOnBackInvokedDispatcher mImeDispatcher; private Boolean mBackCallbackRegistered = false; - private final OnBackInvokedCallback mCompatBackCallback = this::compatHandleBack; + private final CompatOnBackInvokedCallback mCompatBackCallback = this::compatHandleBack; /** * Returns whether {@link InputMethodService} is responsible for rendering the back button and diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 9679a6ab3acb..eb2d64727fc1 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1139,7 +1139,7 @@ public abstract class WallpaperService extends Service { if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE, mDisplay.getDisplayId(), mRequestedVisibilities, inputChannel, - mInsetsState, mTempControls) < 0) { + mInsetsState, mTempControls, new Rect()) < 0) { Log.w(TAG, "Failed to add window while updating wallpaper surface."); return; } @@ -1171,8 +1171,7 @@ public abstract class WallpaperService extends Service { mInsetsState.getDisplayCutoutSafe(displayCutoutSafe); mWindowLayout.computeFrames(mLayout, mInsetsState, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(), mWidth, - mHeight, mRequestedVisibilities, null /* attachedWindowFrame */, - 1f /* compatScale */, mWinFrames); + mHeight, mRequestedVisibilities, 1f /* compatScale */, mWinFrames); mSession.updateLayout(mWindow, mLayout, 0 /* flags */, mWinFrames, mWidth, mHeight); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 649accd1126d..4bf68e23b79f 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -50,13 +50,15 @@ interface IWindowSession { int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, in InsetsVisibilities requestedVisibilities, out InputChannel outInputChannel, out InsetsState insetsState, - out InsetsSourceControl[] activeControls); + out InsetsSourceControl[] activeControls, out Rect attachedFrame); int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, in int userId, in InsetsVisibilities requestedVisibilities, out InputChannel outInputChannel, - out InsetsState insetsState, out InsetsSourceControl[] activeControls); + out InsetsState insetsState, out InsetsSourceControl[] activeControls, + out Rect attachedFrame); int addToDisplayWithoutInputChannel(IWindow window, in WindowManager.LayoutParams attrs, - in int viewVisibility, in int layerStackId, out InsetsState insetsState); + in int viewVisibility, in int layerStackId, out InsetsState insetsState, + out Rect attachedFrame); @UnsupportedAppUsage void remove(IWindow window); @@ -384,4 +386,9 @@ interface IWindowSession { * Clears a touchable region set by {@link #setInsets}. */ void clearTouchableRegion(IWindow window); + + /** + * Returns whether this window needs to cancel draw and retry later. + */ + boolean cancelDraw(IWindow window); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 294d7d6e2bc6..1289548d5634 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -60,13 +60,11 @@ import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowLayout.UNSPECIFIED_LENGTH; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED; @@ -77,13 +75,13 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; +import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW; import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER; @@ -196,6 +194,7 @@ import android.view.contentcapture.MainContentCaptureSession; import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; import android.window.ClientWindowFrames; +import android.window.CompatOnBackInvokedCallback; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; import android.window.SurfaceSyncer; @@ -339,13 +338,12 @@ public final class ViewRootImpl implements ViewParent, /** * The top level {@link OnBackInvokedDispatcher}. */ - private final WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher = - new WindowOnBackInvokedDispatcher(); + private final WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher; /** * Compatibility {@link OnBackInvokedCallback} that dispatches KEYCODE_BACK events * to view root for apps using legacy back behavior. */ - private OnBackInvokedCallback mCompatOnBackInvokedCallback; + private CompatOnBackInvokedCallback mCompatOnBackInvokedCallback; /** * Callback for notifying about global configuration changes. @@ -566,8 +564,6 @@ public final class ViewRootImpl implements ViewParent, private final WindowLayout mWindowLayout; - private ViewRootImpl mParentViewRoot; - // This is used to reduce the race between window focus changes being dispatched from // the window manager and input events coming through the input system. @GuardedBy("this") @@ -601,6 +597,14 @@ public final class ViewRootImpl implements ViewParent, */ private boolean mSyncBuffer = false; + /** + * Flag to determine whether the client needs to check with WMS if it can draw. WMS will notify + * the client that it can't draw if we're still in the middle of a sync set that includes this + * window. Once the sync is complete, the window can resume drawing. This is to ensure we don't + * deadlock the client by trying to request draws when there may not be any buffers available. + */ + private boolean mCheckIfCanDraw = false; + int mSyncSeqId = 0; int mLastSyncSeqId = 0; @@ -962,6 +966,8 @@ public final class ViewRootImpl implements ViewParent, mFastScrollSoundEffectsEnabled = audioManager.areNavigationRepeatSoundEffectsEnabled(); mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS; + mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher( + context.getApplicationInfo().isOnBackInvokedCallbackEnabled()); } public static void addFirstDrawHandler(Runnable callback) { @@ -1185,7 +1191,6 @@ public final class ViewRootImpl implements ViewParent, if (panelParentView != null) { mAttachInfo.mPanelParentWindowToken = panelParentView.getApplicationWindowToken(); - mParentViewRoot = panelParentView.getViewRootImpl(); } mAdded = true; int res; /* = WindowManagerImpl.ADD_OKAY; */ @@ -1216,14 +1221,21 @@ public final class ViewRootImpl implements ViewParent, collectViewAttributes(); adjustLayoutParamsForCompatibility(mWindowAttributes); controlInsetsForCompatibility(mWindowAttributes); + + Rect attachedFrame = new Rect(); res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), userId, mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets, - mTempControls); + mTempControls, attachedFrame); + if (!attachedFrame.isValid()) { + attachedFrame = null; + } if (mTranslator != null) { mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets); mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls); + mTranslator.translateRectInScreenToAppWindow(attachedFrame); } + mTmpFrames.attachedFrame = attachedFrame; } catch (RemoteException e) { mAdded = false; mView = null; @@ -1250,8 +1262,8 @@ public final class ViewRootImpl implements ViewParent, mWindowLayout.computeFrames(mWindowAttributes, state, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(), UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH, - mInsetsController.getRequestedVisibilities(), - getAttachedWindowFrame(), 1f /* compactScale */, mTmpFrames); + mInsetsController.getRequestedVisibilities(), 1f /* compactScale */, + mTmpFrames); setFrame(mTmpFrames.frame); registerBackCallbackOnWindow(); if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { @@ -1373,14 +1385,6 @@ public final class ViewRootImpl implements ViewParent, } } - private Rect getAttachedWindowFrame() { - final int type = mWindowAttributes.type; - final boolean layoutAttached = (mParentViewRoot != null - && type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW - && type != TYPE_APPLICATION_ATTACHED_DIALOG); - return layoutAttached ? mParentViewRoot.mWinFrame : null; - } - /** * Register any kind of listeners if setView was success. */ @@ -1738,16 +1742,20 @@ public final class ViewRootImpl implements ViewParent, final Rect frame = frames.frame; final Rect displayFrame = frames.displayFrame; + final Rect attachedFrame = frames.attachedFrame; if (mTranslator != null) { mTranslator.translateRectInScreenToAppWindow(frame); mTranslator.translateRectInScreenToAppWindow(displayFrame); + mTranslator.translateRectInScreenToAppWindow(attachedFrame); } final boolean frameChanged = !mWinFrame.equals(frame); final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration); + final boolean attachedFrameChanged = LOCAL_LAYOUT + && !Objects.equals(mTmpFrames.attachedFrame, attachedFrame); final boolean displayChanged = mDisplay.getDisplayId() != displayId; final boolean resizeModeChanged = mResizeMode != resizeMode; - if (msg == MSG_RESIZED && !frameChanged && !configChanged && !displayChanged - && !resizeModeChanged && !forceNextWindowRelayout) { + if (msg == MSG_RESIZED && !frameChanged && !configChanged && !attachedFrameChanged + && !displayChanged && !resizeModeChanged && !forceNextWindowRelayout) { return; } @@ -1765,6 +1773,9 @@ public final class ViewRootImpl implements ViewParent, setFrame(frame); mTmpFrames.displayFrame.set(displayFrame); + if (mTmpFrames.attachedFrame != null && attachedFrame != null) { + mTmpFrames.attachedFrame.set(attachedFrame); + } if (mDragResizing && mUseMTRenderer) { boolean fullscreen = frame.equals(mPendingBackDropFrame); @@ -2698,6 +2709,9 @@ public final class ViewRootImpl implements ViewParent, mIsInTraversal = true; mWillDrawSoon = true; + boolean cancelDraw = false; + boolean isSyncRequest = false; + boolean windowSizeMayChange = false; WindowManager.LayoutParams lp = mWindowAttributes; @@ -2967,6 +2981,8 @@ public final class ViewRootImpl implements ViewParent, mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED; } relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); + cancelDraw = (relayoutResult & RELAYOUT_RES_CANCEL_AND_REDRAW) + == RELAYOUT_RES_CANCEL_AND_REDRAW; final boolean dragResizing = mPendingDragResizing; if (mSyncSeqId > mLastSyncSeqId) { mLastSyncSeqId = mSyncSeqId; @@ -2975,6 +2991,7 @@ public final class ViewRootImpl implements ViewParent, } reportNextDraw(); mSyncBuffer = true; + isSyncRequest = true; } final boolean surfaceControlChanged = @@ -3263,6 +3280,19 @@ public final class ViewRootImpl implements ViewParent, } } } else { + // If a relayout isn't going to happen, we still need to check if this window can draw + // when mCheckIfCanDraw is set. This is because it means we had a sync in the past, but + // have not been told by WMS that the sync is complete and that we can continue to draw + if (mCheckIfCanDraw) { + try { + cancelDraw = mWindowSession.cancelDraw(mWindow); + if (DEBUG_BLAST) { + Log.d(mTag, "cancelDraw returned " + cancelDraw); + } + } catch (RemoteException e) { + } + } + // Not the first pass and no window/insets/visibility change but the window // may have moved and we need check that and if so to update the left and right // in the attach info. We translate only the window frame since on window move @@ -3481,7 +3511,9 @@ public final class ViewRootImpl implements ViewParent, reportNextDraw(); } - boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw(); + mCheckIfCanDraw = isSyncRequest || cancelDraw; + + boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || cancelDraw; if (!cancelAndRedraw) { createSyncIfNeeded(); } @@ -8036,7 +8068,7 @@ public final class ViewRootImpl implements ViewParent, mWindowLayout.computeFrames(mWindowAttributes, state, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(), requestedWidth, requestedHeight, mInsetsController.getRequestedVisibilities(), - getAttachedWindowFrame(), 1f /* compatScale */, mTmpFrames); + 1f /* compatScale */, mTmpFrames); mWindowSession.updateLayout(mWindow, params, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mTmpFrames, @@ -8056,6 +8088,7 @@ public final class ViewRootImpl implements ViewParent, if (mTranslator != null) { mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame); mTranslator.translateRectInScreenToAppWindow(mTmpFrames.displayFrame); + mTranslator.translateRectInScreenToAppWindow(mTmpFrames.attachedFrame); mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets); mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls); } @@ -10854,13 +10887,6 @@ public final class ViewRootImpl implements ViewParent, OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback); } - private void unregisterCompatOnBackInvokedCallback() { - if (mCompatOnBackInvokedCallback != null) { - mOnBackInvokedDispatcher.unregisterOnBackInvokedCallback(mCompatOnBackInvokedCallback); - mCompatOnBackInvokedCallback = null; - } - } - @Override public void setTouchableRegion(Region r) { if (r != null) { diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java index c320b262ebd7..9b6b2b906e8e 100644 --- a/core/java/android/view/WindowLayout.java +++ b/core/java/android/view/WindowLayout.java @@ -66,14 +66,15 @@ public class WindowLayout { public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state, Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode, int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities, - Rect attachedWindowFrame, float compatScale, ClientWindowFrames outFrames) { + float compatScale, ClientWindowFrames frames) { final int type = attrs.type; final int fl = attrs.flags; final int pfl = attrs.privateFlags; final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN; - final Rect outDisplayFrame = outFrames.displayFrame; - final Rect outParentFrame = outFrames.parentFrame; - final Rect outFrame = outFrames.frame; + final Rect attachedWindowFrame = frames.attachedFrame; + final Rect outDisplayFrame = frames.displayFrame; + final Rect outParentFrame = frames.parentFrame; + final Rect outFrame = frames.frame; // Compute bounds restricted by insets final Insets insets = state.calculateInsets(windowBounds, attrs.getFitInsetsTypes(), @@ -104,7 +105,7 @@ public class WindowLayout { final DisplayCutout cutout = state.getDisplayCutout(); final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect; displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe); - outFrames.isParentFrameClippedByDisplayCutout = false; + frames.isParentFrameClippedByDisplayCutout = false; if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !cutout.isEmpty()) { // Ensure that windows with a non-ALWAYS display cutout mode are laid out in // the cutout safe zone. @@ -167,7 +168,7 @@ public class WindowLayout { if (!attachedInParent && !floatingInScreenWindow) { mTempRect.set(outParentFrame); outParentFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars); - outFrames.isParentFrameClippedByDisplayCutout = !mTempRect.equals(outParentFrame); + frames.isParentFrameClippedByDisplayCutout = !mTempRect.equals(outParentFrame); } outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars); } @@ -287,12 +288,9 @@ public class WindowLayout { } } - if (DEBUG) Log.d(TAG, "computeWindowFrames " + attrs.getTitle() - + " outFrames=" + outFrames + if (DEBUG) Log.d(TAG, "computeFrames " + attrs.getTitle() + + " frames=" + frames + " windowBounds=" + windowBounds.toShortString() - + " attachedWindowFrame=" + (attachedWindowFrame != null - ? attachedWindowFrame.toShortString() - : "null") + " requestedWidth=" + requestedWidth + " requestedHeight=" + requestedHeight + " compatScale=" + compatScale diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b818a41293ca..dd990e75e3cc 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2591,6 +2591,7 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SYSTEM_ERROR, PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, + PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH, PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME, @@ -2652,6 +2653,10 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, name = "FORCE_STATUS_BAR_VISIBLE"), @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, + equals = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, + name = "LAYOUT_SIZE_EXTENDED_BY_CUTOUT"), + @ViewDebug.FlagToString( mask = PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, equals = PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, name = "FORCE_DECOR_VIEW_VISIBILITY"), diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 85a5762f7f3d..25445abefca2 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -83,6 +83,11 @@ public final class WindowManagerGlobal { public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 1 << 3; /** + * The window manager has told the window it cannot draw this frame and should retry again. + */ + public static final int RELAYOUT_RES_CANCEL_AND_REDRAW = 1 << 4; + + /** * Flag for relayout: the client will be later giving * internal insets; as a result, the window will not impact other window * layouts until the insets are given. diff --git a/core/java/android/view/WindowlessWindowLayout.java b/core/java/android/view/WindowlessWindowLayout.java index 7cc50c579d0d..5bec5b6b6722 100644 --- a/core/java/android/view/WindowlessWindowLayout.java +++ b/core/java/android/view/WindowlessWindowLayout.java @@ -30,10 +30,10 @@ public class WindowlessWindowLayout extends WindowLayout { public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state, Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode, int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities, - Rect attachedWindowFrame, float compatScale, ClientWindowFrames outFrames) { - outFrames.frame.set(0, 0, attrs.width, attrs.height); - outFrames.displayFrame.set(outFrames.frame); - outFrames.parentFrame.set(outFrames.frame); + float compatScale, ClientWindowFrames frames) { + frames.frame.set(0, 0, attrs.width, attrs.height); + frames.displayFrame.set(frames.frame); + frames.parentFrame.set(frames.frame); } } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index a212348a2315..3a72f6e069a5 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -149,7 +149,7 @@ public class WindowlessWindowManager implements IWindowSession { public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Rect outAttachedFrame) { final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession) .setFormat(attrs.format) .setBLASTLayer() @@ -181,6 +181,7 @@ public class WindowlessWindowManager implements IWindowSession { synchronized (this) { mStateForWindow.put(window.asBinder(), state); } + outAttachedFrame.set(0, 0, -1, -1); final int res = WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE | WindowManagerGlobal.ADD_FLAG_USE_BLAST; @@ -196,15 +197,15 @@ public class WindowlessWindowManager implements IWindowSession { public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Rect outAttachedFrame) { return addToDisplay(window, attrs, viewVisibility, displayId, requestedVisibilities, - outInputChannel, outInsetsState, outActiveControls); + outInputChannel, outInsetsState, outActiveControls, outAttachedFrame); } @Override public int addToDisplayWithoutInputChannel(android.view.IWindow window, android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId, - android.view.InsetsState insetsState) { + android.view.InsetsState insetsState, Rect outAttachedFrame) { return 0; } @@ -552,4 +553,9 @@ public class WindowlessWindowManager implements IWindowSession { } } } + + @Override + public boolean cancelDraw(IWindow window) { + return false; + } } diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java index 51f3fe2551ad..929e81ed9044 100644 --- a/core/java/android/window/ClientWindowFrames.java +++ b/core/java/android/window/ClientWindowFrames.java @@ -17,6 +17,7 @@ package android.window; import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -40,6 +41,12 @@ public class ClientWindowFrames implements Parcelable { */ public final @NonNull Rect parentFrame = new Rect(); + /** + * The frame this window attaches to. If this is not null, this is the frame of the parent + * window. + */ + public @Nullable Rect attachedFrame; + public boolean isParentFrameClippedByDisplayCutout; public ClientWindowFrames() { @@ -49,6 +56,9 @@ public class ClientWindowFrames implements Parcelable { frame.set(other.frame); displayFrame.set(other.displayFrame); parentFrame.set(other.parentFrame); + if (other.attachedFrame != null) { + attachedFrame = new Rect(other.attachedFrame); + } isParentFrameClippedByDisplayCutout = other.isParentFrameClippedByDisplayCutout; } @@ -61,6 +71,7 @@ public class ClientWindowFrames implements Parcelable { frame.readFromParcel(in); displayFrame.readFromParcel(in); parentFrame.readFromParcel(in); + attachedFrame = in.readTypedObject(Rect.CREATOR); isParentFrameClippedByDisplayCutout = in.readBoolean(); } @@ -69,6 +80,7 @@ public class ClientWindowFrames implements Parcelable { frame.writeToParcel(dest, flags); displayFrame.writeToParcel(dest, flags); parentFrame.writeToParcel(dest, flags); + dest.writeTypedObject(attachedFrame, flags); dest.writeBoolean(isParentFrameClippedByDisplayCutout); } @@ -78,6 +90,7 @@ public class ClientWindowFrames implements Parcelable { return "ClientWindowFrames{frame=" + frame.toShortString(sb) + " display=" + displayFrame.toShortString(sb) + " parentFrame=" + parentFrame.toShortString(sb) + + (attachedFrame != null ? " attachedFrame=" + attachedFrame.toShortString() : "") + " parentClippedByDisplayCutout=" + isParentFrameClippedByDisplayCutout + "}"; } diff --git a/core/java/android/window/CompatOnBackInvokedCallback.java b/core/java/android/window/CompatOnBackInvokedCallback.java new file mode 100644 index 000000000000..81d7291d9f88 --- /dev/null +++ b/core/java/android/window/CompatOnBackInvokedCallback.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 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 android.window; + +/** + * Marker interface for {@link OnBackInvokedCallback} used for backward compatibility between the + * new system back and the old back event dispatching. Callbacks implementing this interface are + * allowed to be registered even if <code>enableOnbackInvoked</code> is set to false in the + * application manifest. + * @hide + */ +public interface CompatOnBackInvokedCallback extends OnBackInvokedCallback{ + + @Override + void onBackInvoked(); +} diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java index 10d43e89a09d..8ad109317f4b 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import android.util.Pair; +import android.window.WindowOnBackInvokedDispatcher.Checker; import java.util.ArrayList; import java.util.List; @@ -50,6 +51,11 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { private final Object mLock = new Object(); private OnBackInvokedDispatcher mActualDispatcher = null; private ImeOnBackInvokedDispatcher mImeDispatcher; + private final Checker mChecker; + + public ProxyOnBackInvokedDispatcher(boolean applicationCallBackEnabled) { + mChecker = new Checker(applicationCallBackEnabled); + } @Override public void registerOnBackInvokedCallback( @@ -58,11 +64,9 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { Log.v(TAG, String.format("Proxy register %s. mActualDispatcher=%s", callback, mActualDispatcher)); } - if (priority < 0) { - throw new IllegalArgumentException("Application registered OnBackInvokedCallback " - + "cannot have negative priority. Priority: " + priority); + if (mChecker.checkApplicationCallbackRegistration(priority, callback)) { + registerOnBackInvokedCallbackUnchecked(callback, priority); } - registerOnBackInvokedCallbackUnchecked(callback, priority); } @Override diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 1d0bc5a6f0ba..d147524d3b3d 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -30,6 +30,7 @@ import android.view.IWindowSession; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; +import java.util.Objects; import java.util.TreeMap; /** @@ -62,6 +63,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { /** Holds all callbacks by priorities. */ private final TreeMap<Integer, ArrayList<OnBackInvokedCallback>> mOnBackInvokedCallbacks = new TreeMap<>(); + private final Checker mChecker; + + public WindowOnBackInvokedDispatcher(boolean applicationCallBackEnabled) { + mChecker = new Checker(applicationCallBackEnabled); + } /** * Sends the pending top callback (if one exists) to WM when the view root @@ -86,14 +92,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @Override public void registerOnBackInvokedCallback( @Priority int priority, @NonNull OnBackInvokedCallback callback) { - if (priority < 0) { - throw new IllegalArgumentException("Application registered OnBackInvokedCallback " - + "cannot have negative priority. Priority: " + priority); + if (mChecker.checkApplicationCallbackRegistration(priority, callback)) { + registerOnBackInvokedCallbackUnchecked(callback, priority); } - registerOnBackInvokedCallbackUnchecked(callback, priority); } - private void registerOnBackInvokedCallbackUnchecked( + /** + * Register a callback bypassing platform checks. This is used to register compatibility + * callbacks. + */ + public void registerOnBackInvokedCallbackUnchecked( @NonNull OnBackInvokedCallback callback, @Priority int priority) { if (mImeDispatcher != null) { mImeDispatcher.registerOnBackInvokedCallback(priority, callback); @@ -203,6 +211,14 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { return null; } + /** + * Returns the checker used to check whether a callback can be registered + */ + @NonNull + public Checker getChecker() { + return mChecker; + } + static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub { private final WeakReference<OnBackInvokedCallback> mCallback; @@ -289,4 +305,41 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { mImeDispatcher = imeDispatcher; } + + + /** + * Class used to check whether a callback can be registered or not. This is meant to be + * shared with {@link ProxyOnBackInvokedDispatcher} which needs to do the same checks. + */ + public static class Checker { + + private final boolean mApplicationCallBackEnabled; + + public Checker(boolean applicationCallBackEnabled) { + mApplicationCallBackEnabled = applicationCallBackEnabled; + } + + /** + * Checks whether the given callback can be registered with the given priority. + * @return true if the callback can be added. + * @throws IllegalArgumentException if the priority is negative. + */ + public boolean checkApplicationCallbackRegistration(int priority, + OnBackInvokedCallback callback) { + if (!mApplicationCallBackEnabled + && !(callback instanceof CompatOnBackInvokedCallback)) { + Log.w("OnBackInvokedCallback", + "OnBackInvokedCallback is not enabled for the application." + + "\nSet 'android:enableOnBackInvokedCallback=\"true\"' in the" + + " application manifest."); + return false; + } + if (priority < 0) { + throw new IllegalArgumentException("Application registered OnBackInvokedCallback " + + "cannot have negative priority. Priority: " + priority); + } + Objects.requireNonNull(callback); + return true; + } + } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 66abe30d0123..1dedec366b75 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1002,6 +1002,7 @@ public class ChooserActivity extends ResolverActivity implements mShouldDisplayLandscape = shouldDisplayLandscape(newConfig.orientation); mMaxTargetsPerRow = getResources().getInteger(R.integer.config_chooser_max_targets_per_row); + mChooserMultiProfilePagerAdapter.setMaxTargetsPerRow(mMaxTargetsPerRow); adjustPreviewWidth(newConfig.orientation, null); updateStickyContentPreview(); updateTabPadding(); diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java index e6cc62472f5c..df1130be5ec6 100644 --- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java @@ -93,6 +93,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd return profileDescriptor; } + public void setMaxTargetsPerRow(int maxTargetsPerRow) { + mMaxTargetsPerRow = maxTargetsPerRow; + } + RecyclerView getListViewForIndex(int index) { return getItem(index).recyclerView; } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 6829f3da5717..98d4c5976adc 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4503,10 +4503,13 @@ public class BatteryStatsImpl extends BatteryStats { for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) { entry.setValue(entry.getValue() | TAG_FIRST_OCCURRENCE_FLAG); } + // Make a copy of mHistoryCur. + HistoryItem copy = new HistoryItem(); + copy.setTo(cur); + // startRecordingHistory will reset mHistoryCur. startRecordingHistory(elapsedRealtimeMs, uptimeMs, false); - HistoryItem newItem = new HistoryItem(); - newItem.setTo(cur); - addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem); + // Add the copy into history buffer. + addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy); return; } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index e258fc19a75f..fb38bba8ee16 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -342,8 +342,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { boolean mDecorFitsSystemWindows = true; - private final ProxyOnBackInvokedDispatcher mProxyOnBackInvokedDispatcher = - new ProxyOnBackInvokedDispatcher(); + private final ProxyOnBackInvokedDispatcher mProxyOnBackInvokedDispatcher; static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( @@ -358,6 +357,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mLayoutInflater = LayoutInflater.from(context); mRenderShadowsInCompositor = Settings.Global.getInt(context.getContentResolver(), DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 1) != 0; + mProxyOnBackInvokedDispatcher = new ProxyOnBackInvokedDispatcher( + context.getApplicationInfo().isOnBackInvokedCallbackEnabled()); } /** diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml index 0756d68063f5..fd787f6ea470 100644 --- a/core/res/res/layout/notification_template_material_base.xml +++ b/core/res/res/layout/notification_template_material_base.xml @@ -138,7 +138,7 @@ </LinearLayout> - <ImageView + <com.android.internal.widget.CachingIconView android:id="@+id/right_icon" android:layout_width="@dimen/notification_right_icon_size" android:layout_height="@dimen/notification_right_icon_size" @@ -150,6 +150,8 @@ android:clipToOutline="true" android:importantForAccessibility="no" android:scaleType="centerCrop" + android:maxDrawableWidth="@dimen/notification_right_icon_size" + android:maxDrawableHeight="@dimen/notification_right_icon_size" /> <FrameLayout diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml index f163ed5f955a..8b3b795f7473 100644 --- a/core/res/res/layout/notification_template_right_icon.xml +++ b/core/res/res/layout/notification_template_right_icon.xml @@ -13,7 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<ImageView +<com.android.internal.widget.CachingIconView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/right_icon" android:layout_width="@dimen/notification_right_icon_size" @@ -25,4 +25,6 @@ android:clipToOutline="true" android:importantForAccessibility="no" android:scaleType="centerCrop" + android:maxDrawableWidth="@dimen/notification_right_icon_size" + android:maxDrawableHeight="@dimen/notification_right_icon_size" /> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 66da2194e250..ea2f6b0460f7 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un proveïdor de reparacions."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"No es pot crear el model facial. Torna-ho a provar."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Massa brillant Prova una il·luminació més suau."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prova una il·luminació més brillant"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prova amb més il·luminació"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Allunya\'t del telèfon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Apropa el telèfon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mou el telèfon més amunt"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index aa94682722ca..12821fe1527c 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -81,8 +81,8 @@ <string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"Emergency calling unavailable"</string> <string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"No voice service"</string> <string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"No voice service or emergency calling"</string> - <string name="RestrictedStateContent" msgid="7693575344608618926">"Temporarily turned off by your operator"</string> - <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Temporarily turned off by your operator for SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string> + <string name="RestrictedStateContent" msgid="7693575344608618926">"Temporarily turned off by your carrier"</string> + <string name="RestrictedStateContentMsimTemplate" msgid="5228235722511044687">"Temporarily turned off by your carrier for SIM <xliff:g id="SIMNUMBER">%d</xliff:g>"</string> <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Can’t reach mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Try changing preferred network. Tap to change."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Emergency calling unavailable"</string> @@ -124,10 +124,10 @@ <string name="roamingTextSearching" msgid="5323235489657753486">"Searching for Service"</string> <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Couldn’t set up Wi‑Fi calling"</string> <string-array name="wfcOperatorErrorAlertMessages"> - <item msgid="468830943567116703">"To make calls and send messages over Wi-Fi, first ask your operator to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="468830943567116703">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> - <item msgid="4795145070505729156">"Issue registering Wi‑Fi calling with your operator: <xliff:g id="CODE">%1$s</xliff:g>"</item> + <item msgid="4795145070505729156">"Issue registering Wi‑Fi calling with your carrier: <xliff:g id="CODE">%1$s</xliff:g>"</item> </string-array> <!-- no translation found for wfcSpnFormat_spn (2982505428519096311) --> <skip /> @@ -190,7 +190,7 @@ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Too many password attempts"</string> <string name="device_ownership_relinquished" msgid="4080886992183195724">"Admin relinquished device for personal use"</string> <string name="network_logging_notification_title" msgid="554983187553845004">"Device is managed"</string> - <string name="network_logging_notification_text" msgid="1327373071132562512">"Your organisation manages this device and may monitor network traffic. Tap for details."</string> + <string name="network_logging_notification_text" msgid="1327373071132562512">"Your organization manages this device and may monitor network traffic. Tap for details."</string> <string name="location_changed_notification_title" msgid="3620158742816699316">"Apps can access your location"</string> <string name="location_changed_notification_text" msgid="7158423339982706912">"Contact your IT admin to find out more"</string> <string name="geofencing_service" msgid="3826902410740315456">"Geofencing service"</string> @@ -203,7 +203,7 @@ <string name="device_policy_manager_service" msgid="5085762851388850332">"Device Policy manager service"</string> <string name="music_recognition_manager_service" msgid="7481956037950276359">"Music recognition manager service"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> - <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> + <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organization\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> <string name="personal_apps_suspension_title" msgid="7561416677884286600">"Turn on your work profile"</string> <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string> @@ -726,8 +726,8 @@ <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string> <string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string> <string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string> - <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string> - <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string> + <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string> + <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string> <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string> <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string> <string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string> @@ -738,10 +738,10 @@ <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string> <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string> <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string> - <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string> - <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string> - <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string> - <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string> + <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string> + <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string> + <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to carrier services"</string> + <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to carrier services. Should never be needed for normal apps."</string> <string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string> <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Allows the app to read and write Do Not Disturb configuration."</string> <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start view permission usage"</string> @@ -1335,7 +1335,7 @@ <string name="sim_added_message" msgid="6602906609509958680">"Restart your device to access the mobile network."</string> <string name="sim_restart_button" msgid="8481803851341190038">"Restart"</string> <string name="install_carrier_app_notification_title" msgid="5712723402213090102">"Activate mobile service"</string> - <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Download the mobile app to activate your new SIM"</string> + <string name="install_carrier_app_notification_text" msgid="2781317581274192728">"Download the carrier app to activate your new SIM"</string> <string name="install_carrier_app_notification_text_app_name" msgid="4086877327264106484">"Download the <xliff:g id="APP_NAME">%1$s</xliff:g> app to activate your new SIM"</string> <string name="install_carrier_app_notification_button" msgid="6257740533102594290">"Download app"</string> <string name="carrier_app_notification_title" msgid="5815477368072060250">"New SIM inserted"</string> @@ -1587,7 +1587,7 @@ <string name="ssl_certificate_is_valid" msgid="7293675884598527081">"This certificate is valid."</string> <string name="issued_to" msgid="5975877665505297662">"Issued to:"</string> <string name="common_name" msgid="1486334593631798443">"Common name:"</string> - <string name="org_name" msgid="7526331696464255245">"Organisation:"</string> + <string name="org_name" msgid="7526331696464255245">"Organization:"</string> <string name="org_unit" msgid="995934486977223076">"Organisational unit:"</string> <string name="issued_by" msgid="7872459822431585684">"Issued by:"</string> <string name="validity_period" msgid="1717724283033175968">"Validity:"</string> @@ -1640,7 +1640,7 @@ <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string> <string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string> <string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string> - <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string> + <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string> <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string> <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string> <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 9c08bcb2306f..e673a8b8946d 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -307,7 +307,7 @@ <string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string> <string name="permgrouplab_storage" msgid="17339216290379241">"Fitxategiak"</string> <string name="permgroupdesc_storage" msgid="5378659041354582769">"gailuko fitxategiak atzitu"</string> - <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"musika eta audioa"</string> + <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Musika eta audioa"</string> <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"atzitu gailuko musika eta audioak"</string> <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Argazkiak eta bideoak"</string> <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"atzitu gailuko argazkiak eta bideoak"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index fad957ae74d5..7b97084883d4 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -644,7 +644,7 @@ <string name="face_acquired_too_right" msgid="6245286514593540859">"تلفن را بهسمت چپ ببرید"</string> <string name="face_acquired_too_left" msgid="9201762240918405486">"تلفن را بهسمت راست ببرید"</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"لطفاً مستقیم به دستگاه نگه کنید."</string> - <string name="face_acquired_not_detected" msgid="1057966913397548150">"چهرهتان دیده نمیشود. تلفن را همسطح چشمانتان نگه دارید."</string> + <string name="face_acquired_not_detected" msgid="1057966913397548150">"چهره دیده نمیشود. تلفن را همسطح چشمانتان نگه دارید."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"حرکت خیلی زیاد است. تلفن را ثابت نگهدارید."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"لطفاً چهرهتان را مجدداً ثبت کنید."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"چهره شناسایی نشد. دوباره امتحان کنید."</string> @@ -2044,7 +2044,7 @@ <string name="harmful_app_warning_title" msgid="8794823880881113856">"برنامه مضر شناسایی شد"</string> <string name="log_access_confirmation_title" msgid="2343578467290592708">"به <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> اجازه میدهید به همه گزارشهای دستگاه دسترسی داشته باشد؟"</string> <string name="log_access_confirmation_allow" msgid="5302517782599389507">"مجاز کردن دسترسی یکباره"</string> - <string name="log_access_confirmation_deny" msgid="7685790957455099845">"مجاز نیست"</string> + <string name="log_access_confirmation_deny" msgid="7685790957455099845">"اجازه ندادن"</string> <string name="log_access_confirmation_body" msgid="6581985716241928135">"گزارشهای دستگاه آنچه را در دستگاهتان رخ میدهد ثبت میکند. برنامهها میتوانند از این گزارشها برای پیدا کردن مشکلات و رفع آنها استفاده کنند.\n\nبرخیاز گزارشها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامههای مورداعتمادتان اجازه دسترسی به همه گزارشهای دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارشهای دستگاه دسترسی داشته باشد، همچنان میتواند به گزارشهای خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخیاز گزارشها یا اطلاعات دستگاهتان دسترسی داشته باشد. بیشتر بدانید"</string> <string name="log_access_do_not_show_again" msgid="1058690599083091552">"دوباره نشان داده نشود"</string> <string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> میخواهد تکههای <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index b7fbf2276e39..40c6e7b5d654 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -651,7 +651,7 @@ <string name="face_acquired_too_different" msgid="2520389515612972889">"Prepoznavanje lica nije uspjelo. Pokušajte ponovo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Malo pomaknite glavu"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Gledajte izravnije prema telefonu"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Gledajte izravnije prema telefonu"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Gledajte ravno u telefon"</string> <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Gledajte izravnije prema telefonu"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Uklonite sve što vam zakriva lice."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Očistite vrh zaslona, uključujući crnu traku"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index efca6624d32e..d8a389455c4b 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -1689,7 +1689,7 @@ <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Кызмат экрандагы нерселерди окуп, аларды башка колдонмолордун үстүнөн көрсөтөт."</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Аракеттерди көрүп, аткаруу"</string> <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Кызмат колдонмодо жасаган аракеттериңизге же түзмөктүн сенсорлоруна көз салып, сиздин атыңыздан буйруктарды берет."</string> - <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Уруксат берүү"</string> + <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Ооба"</string> <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Жок"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index d965fea166ea..bad52d4ab45e 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -637,7 +637,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Sazinieties ar remonta pakalpojumu sniedzēju."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nevar izveidot sejas modeli. Mēģiniet vēlreiz."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Pārāk spilgts. Izmēģiniet maigāku apgaismojumu."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Izmēģiniet spožāku apgaismojumu."</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"Izmēģiniet spožāku apgaismojumu"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Pārvietojiet tālruni tālāk."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Pārvietojiet tālruni tuvāk."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Paceliet tālruni augstāk."</string> @@ -650,13 +650,13 @@ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Lūdzu, atkārtoti reģistrējiet savu seju."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Nevar atpazīt seju. Mēģiniet vēlreiz."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Nedaudz mainiet galvas pozīciju."</string> - <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Skatieties tieši uz tālruni."</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Skatieties tieši uz tālruni."</string> - <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Skatieties tieši uz tālruni."</string> + <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Skatieties tieši uz tālruni"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Skatieties tieši uz tālruni"</string> + <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Skatieties tieši uz tālruni"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Noņemiet visu, kas aizsedz jūsu seju."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Notīriet ekrāna augšdaļu, tostarp melno joslu."</string> - <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Sejai ir jābūt pilnībā redzamai."</string> - <string name="face_acquired_mouth_covering_detected" msgid="615991670821926847">"Sejai ir jābūt pilnībā redzamai."</string> + <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Sejai ir jābūt pilnībā redzamai"</string> + <string name="face_acquired_mouth_covering_detected" msgid="615991670821926847">"Sejai ir jābūt pilnībā redzamai"</string> <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Nevar izveidot sejas modeli. Mēģiniet vēlreiz."</string> <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Konstatētas tumšas brilles. Sejai ir jābūt pilnībā redzamai."</string> <string name="face_acquired_mouth_covering_detected_alt" msgid="1122294982850589766">"Konstatēts sejas aizsegs. Sejai ir jābūt pilnībā redzamai."</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index e182833c6886..87186350faea 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -939,7 +939,7 @@ <string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Запри"</string> <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Премотај назад"</string> <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Брзо премотај напред"</string> - <string name="emergency_calls_only" msgid="3057351206678279851">"Само повици за итни случаи"</string> + <string name="emergency_calls_only" msgid="3057351206678279851">"Само итни повици"</string> <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Мрежата е заклучена"</string> <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM картичката е заклучена со ПУК код."</string> <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Погледнете го Упатството за корисници или контактирајте со Грижа за корисници."</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index c735ff5361d1..1b154004fa00 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"റിപ്പയർ കേന്ദ്രം സന്ദർശിക്കുക."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"മുഖ മോഡൽ സൃഷ്ടിക്കാനാകില്ല. വീണ്ടും ശ്രമിക്കൂ."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"വളരെയധികം തെളിച്ചം. സൗമ്യതയേറിയ പ്രകാശം ശ്രമിക്കൂ."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"തിളക്കമേറിയ ലൈറ്റിംഗ് പരീക്ഷിച്ച് നോക്കൂ"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"കൂടുതൽ വെളിച്ചമുള്ളയിടത്ത് പരീക്ഷിച്ച് നോക്കൂ"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ഫോൺ കൂടുതൽ ദൂരേയ്ക്ക് നീക്കുക"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ഫോൺ അടുത്തേക്ക് നീക്കുക"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ഫോൺ മുകളിലേക്ക് ഉയർത്തുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 8265c910e5f6..9f1453503e28 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -644,7 +644,7 @@ <string name="face_acquired_too_right" msgid="6245286514593540859">"Утсаа зүүн тийш болгоно уу"</string> <string name="face_acquired_too_left" msgid="9201762240918405486">"Утсаа баруун тийш болгоно уу"</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Төхөөрөмж рүүгээ аль болох эгц харна уу."</string> - <string name="face_acquired_not_detected" msgid="1057966913397548150">"Таны нүүрийг харагдахгүй байна. Утсаа нүднийхээ түвшинд барина уу."</string> + <string name="face_acquired_not_detected" msgid="1057966913397548150">"Таны царай харагдахгүй байна. Утсаа нүднийхээ түвшинд барина уу."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Хэт их хөдөлгөөнтэй байна. Утсаа хөдөлгөөнгүй барина уу."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Нүүрээ дахин бүртгүүлнэ үү."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Царайг танихгүй байна. Дахин оролдоно уу."</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 029099b65e8d..580eb35eb0b5 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -638,7 +638,7 @@ <string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string> <string name="face_acquired_too_dark" msgid="7919016380747701228">"Use uma iluminação mais intensa"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste o smartphone"</string> - <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone"</string> + <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone do seu rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o smartphone para cima"</string> <string name="face_acquired_too_low" msgid="4075391872960840081">"Mova o smartphone para baixo"</string> <string name="face_acquired_too_right" msgid="6245286514593540859">"Mova o smartphone para a esquerda"</string> @@ -649,9 +649,9 @@ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registre seu rosto novamente."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Não foi possível reconhecer o rosto Tente de novo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Mude a posição da cabeça ligeiramente"</string> - <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe mais diretamente para o smartphone"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe mais diretamente para o smartphone"</string> - <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Olhe mais diretamente para o smartphone"</string> + <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe diretamente para o smartphone"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe diretamente para o smartphone"</string> + <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Olhe diretamente para o smartphone"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Remova tudo que esteja ocultando seu rosto."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpe a parte superior da tela, inclusive a barra preta"</string> <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Seu rosto precisa estar completamente visível"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 3abe9b3ba115..28412db5586c 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -638,7 +638,7 @@ <string name="face_acquired_too_bright" msgid="8070756048978079164">"Demasiado clara. Experimente uma luz mais suave."</string> <string name="face_acquired_too_dark" msgid="7919016380747701228">"Experimente um local com mais luz"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste ainda mais o telemóvel"</string> - <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o telemóvel"</string> + <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o telemóvel do rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o telemóvel mais para cima"</string> <string name="face_acquired_too_low" msgid="4075391872960840081">"Mova o telemóvel mais para baixo"</string> <string name="face_acquired_too_right" msgid="6245286514593540859">"Mova o telemóvel para a sua esquerda"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 029099b65e8d..580eb35eb0b5 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -638,7 +638,7 @@ <string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string> <string name="face_acquired_too_dark" msgid="7919016380747701228">"Use uma iluminação mais intensa"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste o smartphone"</string> - <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone"</string> + <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone do seu rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o smartphone para cima"</string> <string name="face_acquired_too_low" msgid="4075391872960840081">"Mova o smartphone para baixo"</string> <string name="face_acquired_too_right" msgid="6245286514593540859">"Mova o smartphone para a esquerda"</string> @@ -649,9 +649,9 @@ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registre seu rosto novamente."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Não foi possível reconhecer o rosto Tente de novo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Mude a posição da cabeça ligeiramente"</string> - <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe mais diretamente para o smartphone"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe mais diretamente para o smartphone"</string> - <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Olhe mais diretamente para o smartphone"</string> + <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe diretamente para o smartphone"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe diretamente para o smartphone"</string> + <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Olhe diretamente para o smartphone"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Remova tudo que esteja ocultando seu rosto."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Limpe a parte superior da tela, inclusive a barra preta"</string> <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Seu rosto precisa estar completamente visível"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 4e533527dc60..41efa8d79e3c 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -649,9 +649,9 @@ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Regjistroje përsëri fytyrën tënde."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Fytyra nuk mund të njihet. Provo sërish."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Ndrysho pak pozicionin e kokës"</string> - <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Shiko më shumë drejtpërdrejt telefonit"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Shiko më shumë drejtpërdrejt telefonit"</string> - <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Shiko më shumë drejtpërdrejt telefonit"</string> + <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Shiko më drejtpërdrejt telefonin"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Shiko më drejtpërdrejt telefonin"</string> + <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Shiko më drejtpërdrejt telefonin"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Hiq gjithçka që fsheh fytyrën tënde."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Pastro kreun e ekranit, duke përfshirë shiritin e zi"</string> <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Fytyra jote duhet të jetë plotësisht e dukshme"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index a3a74619658c..e23cbd11099f 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -644,7 +644,7 @@ <string name="face_acquired_too_right" msgid="6245286514593540859">"Sogeza simu upande wako wa kushoto"</string> <string name="face_acquired_too_left" msgid="9201762240918405486">"Sogeza simu upande wako wa kulia"</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Tafadhali angalia kifaa chako moja kwa moja."</string> - <string name="face_acquired_not_detected" msgid="1057966913397548150">"Imeshindwa kuona uso wako. Shikilia simu yako katika usawa wa macho."</string> + <string name="face_acquired_not_detected" msgid="1057966913397548150">"Imeshindwa kuona uso wako. Shikilia simu yako ikilingana na macho."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Inatikisika sana. Ishike simu iwe thabiti."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Tafadhali sajili uso wako tena."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Imeshindwa kutambua uso. Jaribu tena."</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index f562356cdc85..247ca775dec3 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Xizmat koʻrsatish markaziga murojaat qiling."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Yuzingiz modeli yaratilmadi. Qayta urining."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Juda yorqin. Biroz soyaroq joy tanlang."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Atrofingizni yoriting"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"Atrofingizni yanada yoriting"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Telefonni biroz uzoqroq tuting"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Telefonni yaqinroq tuting"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Telefonni teparoq tuting"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 6ca2979871a1..7f6b6795342a 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -644,7 +644,7 @@ <string name="face_acquired_too_right" msgid="6245286514593540859">"Đưa điện thoại sang bên trái"</string> <string name="face_acquired_too_left" msgid="9201762240918405486">"Đưa điện thoại sang bên phải"</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Vui lòng nhìn thẳng vào thiết bị."</string> - <string name="face_acquired_not_detected" msgid="1057966913397548150">"Không thấy khuôn mặt bạn. Cầm điện thoại ngang tầm mắt"</string> + <string name="face_acquired_not_detected" msgid="1057966913397548150">"Không phát hiện thấy khuôn mặt của bạn. Hãy cầm điện thoại ngang tầm mắt"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Thiết bị di chuyển quá nhiều. Giữ yên thiết bị."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vui lòng đăng ký lại khuôn mặt của bạn."</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"Không thể nhận dạng khuôn mặt. Hãy thử lại."</string> @@ -654,7 +654,7 @@ <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"Nhìn thẳng vào điện thoại"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"Hãy loại bỏ mọi thứ che khuất khuôn mặt bạn."</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"Vệ sinh phần đầu màn hình, bao gồm cả thanh màu đen"</string> - <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Toàn bộ khuôn mặt của bạn phải được hiển thị"</string> + <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"Bạn cần cho thấy toàn bộ khuôn mặt của mình"</string> <string name="face_acquired_mouth_covering_detected" msgid="615991670821926847">"Toàn bộ khuôn mặt của bạn phải được hiển thị"</string> <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"Không thể tạo mẫu khuôn mặt của bạn. Hãy thử lại."</string> <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"Đã phát hiện đeo kính đen. Toàn bộ khuôn mặt của bạn phải được hiển thị."</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index cdb797227fa4..018ebee34b04 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"請諮詢維修服務供應商。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"無法建立面部模型,請再試一次。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"影像太亮。請嘗試在更暗的環境下使用。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"請嘗試在更明亮的環境下使用"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"請試用更充足的光線"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"請將手機移遠一點"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"請將手機移近一點"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"請將手機向上移"</string> @@ -644,17 +644,17 @@ <string name="face_acquired_too_right" msgid="6245286514593540859">"請將手機向左移"</string> <string name="face_acquired_too_left" msgid="9201762240918405486">"請將手機向右移"</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"請以更直視的角度看著裝置。"</string> - <string name="face_acquired_not_detected" msgid="1057966913397548150">"看不到您的臉。將手機保持與視線同高。"</string> + <string name="face_acquired_not_detected" msgid="1057966913397548150">"看不到面孔,請將手機放在視線水平。"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"裝置不夠穩定。請拿穩手機。"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"請重新註冊臉孔。"</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"無法辨識面孔,請再試一次。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"請稍微變更頭部的位置"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"盡可能直視手機"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"盡可能直視手機"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"請正面望向手機"</string> <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"盡可能直視手機"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"移除遮住您臉孔的任何東西。"</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"請清理螢幕頂部,包括黑色列"</string> - <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"您必須展示整個面孔。"</string> + <string name="face_acquired_dark_glasses_detected" msgid="7263638432128692048">"必須展示整個面孔"</string> <string name="face_acquired_mouth_covering_detected" msgid="615991670821926847">"您必須展示整個面孔。"</string> <string name="face_acquired_recalibrate_alt" msgid="5702674220280332115">"無法建立面部模型,請再試一次。"</string> <string name="face_acquired_dark_glasses_detected_alt" msgid="4052123776406041972">"偵測到深色眼鏡。您必須展示整個面孔。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index cdca5e5e9b45..453c14a093da 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"請洽詢維修供應商。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"無法建立臉部模型,請再試一次。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"亮度過高,請嘗試使用較柔和的照明方式。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"請試著提高亮度"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"請採用更明亮的光源"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"請將手機拿遠一點"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"請將手機拿近一點"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"請將手機舉高一點"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 7c930cc7410f..381f864adf63 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -636,7 +636,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Vakashela umhlinzeki wokulungisa."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Ayikwazi ukusungula imodeli yobuso bakho. Zama futhi."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Kukhanya kakhulu. Zama ukukhanya okuthambile."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Zama ukukhanyisa okukhanyayo"</string> + <string name="face_acquired_too_dark" msgid="7919016380747701228">"Zama ukukhanyisa okukhudlwana"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Yisa ifoni kude"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Sondeza ifoni eduze"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Yisa ifoni phezulu"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2171987c081e..a8c7bf249ada 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2944,7 +2944,7 @@ <!-- System bluetooth stack package name --> <string name="config_systemBluetoothStack" translatable="false"> - com.android.bluetooth.services + com.android.bluetooth </string> <!-- Flag indicating that the media framework should not allow changes or mute on any @@ -5180,11 +5180,11 @@ <!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. --> <bool name="config_letterboxIsEducationEnabled">false</bool> - <!-- Default min aspect ratio for unresizable apps which is used when an app doesn't specify - android:minAspectRatio in accordance with CDD 7.1.1.2 requirement: - https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio. - An exception will be thrown if the given aspect ratio < 4:3. --> - <item name="config_letterboxDefaultMinAspectRatioForUnresizableApps" format="float" type="dimen">1.5</item> + <!-- Default min aspect ratio for unresizable apps which are eligible for size compat mode. + Values <= 1.0 will be ignored. Activity min/max aspect ratio restrictions will still be + espected so this override can control the maximum screen area that can be occupied by + the app in the letterbox mode. --> + <item name="config_letterboxDefaultMinAspectRatioForUnresizableApps" format="float" type="dimen">0.0</item> <!-- Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. --> <bool name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled">false</bool> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 04857ec756d2..3e4b1cc87ef8 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -161,7 +161,10 @@ <!-- ChooserActivityTest permissions--> <uses-permission android:name="android.permission.SET_CLIP_SOURCE" /> - <application android:theme="@style/Theme" android:supportsRtl="true"> + <application + android:theme="@style/Theme" + android:supportsRtl="true" + android:enableOnBackInvokedCallback="true"> <uses-library android:name="android.test.runner" /> <uses-library android:name="org.apache.http.legacy" android:required="false" /> <meta-data diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index c57aa740124c..f448cb3091e7 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -64,7 +64,7 @@ public class WindowOnBackInvokedDispatcherTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mDispatcher = new WindowOnBackInvokedDispatcher(); + mDispatcher = new WindowOnBackInvokedDispatcher(true /* applicationCallbackEnabled */); mDispatcher.attachToWindow(mWindowSession, mWindow); } diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index b38e1c274b45..82148422aabf 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -84,17 +84,23 @@ import android.service.chooser.ChooserTarget; import android.view.View; import androidx.annotation.CallSuper; +import androidx.test.espresso.matcher.BoundedDiagnosingMatcher; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; +import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.widget.GridLayoutManager; +import com.android.internal.widget.RecyclerView; +import org.hamcrest.Description; import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -1680,6 +1686,25 @@ public class ChooserActivityTest { wrapper.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1")); } + @Test + public void testUpdateMaxTargetsPerRow_columnCountIsUpdated() throws InterruptedException { + updateMaxTargetsPerRowResource(/* targetsPerRow= */ 4); + givenAppTargets(/* appCount= */ 16); + Intent sendIntent = createSendTextIntent(); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + + updateMaxTargetsPerRowResource(/* targetsPerRow= */ 6); + InstrumentationRegistry.getInstrumentation() + .runOnMainSync(() -> activity.onConfigurationChanged( + InstrumentationRegistry.getInstrumentation() + .getContext().getResources().getConfiguration())); + + waitForIdle(); + onView(withIdFromRuntimeResource("resolver_list")) + .check(matches(withGridColumnCount(6))); + } + // This test is too long and too slow and should not be taken as an example for future tests. @Test @Ignore public void testDirectTargetLoggingWithAppTargetNotRankedPortrait() @@ -3063,6 +3088,64 @@ public class ChooserActivityTest { return withText(getRuntimeResourceId(id, "string")); } + private static GridRecyclerSpanCountMatcher withGridColumnCount(int columnCount) { + return new GridRecyclerSpanCountMatcher(Matchers.is(columnCount)); + } + + private static class GridRecyclerSpanCountMatcher extends + BoundedDiagnosingMatcher<View, RecyclerView> { + + private final Matcher<Integer> mIntegerMatcher; + + private GridRecyclerSpanCountMatcher(Matcher<Integer> integerMatcher) { + super(RecyclerView.class); + this.mIntegerMatcher = integerMatcher; + } + + @Override + protected void describeMoreTo(Description description) { + description.appendText("RecyclerView grid layout span count to match: "); + this.mIntegerMatcher.describeTo(description); + } + + @Override + protected boolean matchesSafely(RecyclerView view, Description mismatchDescription) { + int spanCount = ((GridLayoutManager) view.getLayoutManager()).getSpanCount(); + if (this.mIntegerMatcher.matches(spanCount)) { + return true; + } else { + mismatchDescription.appendText("RecyclerView grid layout span count was ") + .appendValue(spanCount); + return false; + } + } + } + + private void givenAppTargets(int appCount) { + List<ResolvedComponentInfo> resolvedComponentInfos = + createResolvedComponentsForTest(appCount); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); + } + + private void updateMaxTargetsPerRowResource(int targetsPerRow) { + ChooserActivityOverrideData.getInstance().resources = Mockito.spy( + InstrumentationRegistry.getInstrumentation().getContext().getResources()); + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getInteger(R.integer.config_chooser_max_targets_per_row)) + .thenReturn(targetsPerRow); + } + // ChooserWrapperActivity inherits from the framework ChooserActivity, so if the framework // resources have been updated since the framework was last built/pushed, the inherited behavior // (which is the focus of our testing) will still be implemented in terms of the old resource diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java index 385879210d4a..dd0e9ff8b5e8 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java @@ -154,19 +154,21 @@ public class BatteryStatsHistoryIteratorTest { for (int i = 0; i < eventCount; i++) { String name = "a" + (i % 10); - assertThat(iterator.next(item)).isTrue(); - // Skip a blank event inserted at the start of every buffer - if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) { + do { assertThat(iterator.next(item)).isTrue(); - } + // Skip a blank event inserted at the start of every buffer + } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE + || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE); + assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_START); assertThat(item.eventTag.string).isEqualTo(name); - assertThat(iterator.next(item)).isTrue(); - if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) { + do { assertThat(iterator.next(item)).isTrue(); - } + } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE + || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE); + assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM | BatteryStats.HistoryItem.EVENT_FLAG_FINISH); assertThat(item.eventTag.string).isEqualTo(name); diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 8d3751e6ad6c..47f70ddf2d42 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -207,8 +207,8 @@ public class ActivityThreadClientTest { final Configuration currentConfig = new Configuration(); assertFalse("Must not report change if no public diff", - shouldReportChange(0 /* publicDiff */, currentConfig, newConfig, - null /* sizeBuckets */, 0 /* handledConfigChanges */)); + shouldReportChange(currentConfig, newConfig, null /* sizeBuckets */, + 0 /* handledConfigChanges */)); final int[] verticalThresholds = {100, 400}; final SizeConfigurationBuckets buckets = new SizeConfigurationBuckets( @@ -221,25 +221,25 @@ public class ActivityThreadClientTest { newConfig.screenHeightDp = 300; assertFalse("Must not report changes if the diff is small and not handled", - shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, - newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + shouldReportChange(currentConfig, newConfig, buckets, + CONFIG_FONT_SCALE /* handledConfigChanges */)); assertTrue("Must report changes if the small diff is handled", - shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, newConfig, - buckets, CONFIG_SCREEN_SIZE /* handledConfigChanges */)); + shouldReportChange(currentConfig, newConfig, buckets, + CONFIG_SCREEN_SIZE /* handledConfigChanges */)); currentConfig.fontScale = 0.8f; newConfig.fontScale = 1.2f; assertTrue("Must report handled changes regardless of small unhandled change", - shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */, - currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + shouldReportChange(currentConfig, newConfig, buckets, + CONFIG_FONT_SCALE /* handledConfigChanges */)); newConfig.screenHeightDp = 500; assertFalse("Must not report changes if there's unhandled big changes", - shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */, - currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */)); + shouldReportChange(currentConfig, newConfig, buckets, + CONFIG_FONT_SCALE /* handledConfigChanges */)); } private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) { 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 242e9ab6beee..b15dce7f3f17 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -642,6 +642,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } private void onActivityConfigurationChanged(@NonNull Activity activity) { + if (activity.isFinishing()) { + // Do nothing if the activity is currently finishing. + return; + } + if (isInPictureInPicture(activity)) { // We don't embed activity when it is in PIP. return; @@ -1119,6 +1124,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } boolean launchPlaceholderIfNecessary(@NonNull Activity activity, boolean isOnCreated) { + if (activity.isFinishing()) { + return false; + } + final TaskFragmentContainer container = getContainerWithActivity(activity); // Don't launch placeholder if the container is occluded. if (container != null && container != getTopActiveContainer(container.getTaskId())) { diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index cfb32050e32f..18086f552ea3 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -25,7 +25,10 @@ import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.annotation.Nullable; import android.app.Activity; +import android.app.ActivityManager; +import android.app.ActivityManager.AppTask; import android.app.Application; +import android.app.WindowConfiguration; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; @@ -180,7 +183,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); return features; - } else if (activity.isInMultiWindowMode()) { + } else if (isTaskInMultiWindowMode(activity)) { // It is recommended not to report any display features in multi-window mode, since it // won't be possible to synchronize the display feature positions with window movement. return features; @@ -204,6 +207,32 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { } /** + * Checks whether the task associated with the activity is in multi-window. If task info is not + * available it defaults to {@code true}. + */ + private boolean isTaskInMultiWindowMode(@NonNull Activity activity) { + final ActivityManager am = activity.getSystemService(ActivityManager.class); + if (am == null) { + return true; + } + + final List<AppTask> appTasks = am.getAppTasks(); + final int taskId = activity.getTaskId(); + AppTask task = null; + for (AppTask t : appTasks) { + if (t.getTaskInfo().taskId == taskId) { + task = t; + break; + } + } + if (task == null) { + // The task might be removed on the server already. + return true; + } + return WindowConfiguration.inMultiWindowMode(task.getTaskInfo().getWindowingMode()); + } + + /** * Returns {@link true} if a {@link Rect} has zero width and zero height, * {@code false} otherwise. */ diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 98b25c8ab087..2afce7fa3c43 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"انقر مرتين بجانب التطبيق لتغيير موضعه."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"حسنًا"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"التوسيع للحصول على مزيد من المعلومات"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"تكبير"</string> + <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 2520267f46d2..df975751ee31 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"এপ্টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ কাষত দুবাৰ টিপক"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুজি পালোঁ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"অধিক তথ্যৰ বাবে বিস্তাৰ কৰক।"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string> + <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 51b60774b2fd..892be9345e3a 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tətbiqin yerini dəyişmək üçün yanına iki dəfə toxunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ətraflı məlumat üçün genişləndirin."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Böyüdün"</string> + <string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index c44afcd74c01..e27ec8ee11bb 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Докоснете два пъти дадено приложение, за да промените позицията му"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Разбрах"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгъване за още информация."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Увеличаване"</string> + <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index fbf39255be08..aadbfa434cf4 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -82,6 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvaput dodirnite pored aplikacije da promijenite njen položaj"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Razumijem"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za više informacija."</string> - <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziraj"</string> - <string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziranje"</string> + <string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index 3ea31cebe5ab..ab672460ce1d 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Fes doble toc al costat d\'una aplicació per canviar-ne la posició"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entesos"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Desplega per obtenir més informació."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximitza"</string> + <string name="close_button_text" msgid="2913281996024033299">"Tanca"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 574ed2616490..d7b1a3889806 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dvojitým klepnutím vedle aplikace změňte její umístění"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozbalením zobrazíte další informace."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovat"</string> + <string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 2fcd37a54bc6..c0acc08cde19 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryk to gange ud for en app for at ændre dens placering"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Udvid for at få flere oplysninger."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimér"</string> + <string name="close_button_text" msgid="2913281996024033299">"Luk"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 07075b591f73..e06bebda8bdf 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Neben einer App doppeltippen, um die Position zu ändern"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Für weitere Informationen maximieren."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximieren"</string> + <string name="close_button_text" msgid="2913281996024033299">"Schließen"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 8f7c741b45e2..c2493287bcb8 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dos veces junto a una aplicación para cambiar su posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mostrar más información"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> + <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index 0d75a5552fe4..0133336e58b8 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Topeltpuudutage rakenduse kõrval, et selle asendit muuta"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeeri"</string> + <string name="close_button_text" msgid="2913281996024033299">"Sule"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 3e95b484d567..20045eff330c 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"در کنار برنامه دوضربه بزنید تا جابهجا شود"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"متوجهام"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"برای اطلاعات بیشتر، گسترده کنید."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"بزرگ کردن"</string> + <string name="close_button_text" msgid="2913281996024033299">"بستن"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index a1e5efbad7b6..2cd265ea82f0 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kaksoisnapauta sovellusta, jos haluat siirtää sitä"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Katso lisätietoja laajentamalla."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Suurenna"</string> + <string name="close_button_text" msgid="2913281996024033299">"Sulje"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index c3f36e60bddc..eb25a8d16434 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Touchez deux fois à côté d\'une application pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développer pour en savoir plus."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string> + <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 1365c22017cf..53358b7a23b7 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Appuyez deux fois à côté d\'une appli pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string> + <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 19430577f181..09977a194fea 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toca dúas veces a carón dunha aplicación para cambiala de posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Despregar para obter máis información."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> + <string name="close_button_text" msgid="2913281996024033299">"Pechar"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 478bfbaed62e..3d83005ba30b 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बगल में दो बार टैप करें"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"बड़ा करें"</string> + <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 4cc183de140a..160651ca67ad 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Եղավ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ծավալեք՝ ավելին իմանալու համար։"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Ծավալել"</string> + <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index af8a8ece437d..fab34868009e 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Ketuk dua kali di samping aplikasi untuk mengubah posisinya"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimalkan"</string> + <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 40a0e176ca29..7ec13c4248e0 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tocca due volte accanto a un\'app per riposizionarla"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Espandi per avere ulteriori informazioni."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Ingrandisci"</string> + <string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 3a7381164e08..8625a2a079da 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"מקישים הקשה כפולה ליד אפליקציה כדי למקם אותה מחדש"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"הבנתי"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"מרחיבים כדי לקבל מידע נוסף."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"הגדלה"</string> + <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index a1585a454322..22cf08b92082 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Қолданбаның орнын ауыстыру үшін жанынан екі рет түртіңіз."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түсінікті"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толығырақ ақпарат алу үшін терезені жайыңыз."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Жаю"</string> + <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 6f516e64ca02..15e8a9041202 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"앱 위치를 조정하려면 앱 옆을 두 번 탭하세요."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"확인"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"추가 정보는 펼쳐서 확인하세요."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"최대화"</string> + <string name="close_button_text" msgid="2913281996024033299">"닫기"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index a7ad006b0347..be72d8e2a22f 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ແຕະສອງເທື່ອໃສ່ຖັດຈາກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ເຂົ້າໃຈແລ້ວ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ຂະຫຍາຍເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string> + <string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 3002492989aa..3fa163bb35c2 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dukart palieskite šalia programos, kad pakeistumėte jos poziciją"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Supratau"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Išskleiskite, jei reikia daugiau informacijos."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Padidinti"</string> + <string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index cce1f5feafb7..90cd4bed63f8 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Veiciet dubultskārienu blakus lietotnei, lai manītu tās pozīciju"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Labi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Izvērsiet, lai iegūtu plašāku informāciju."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizēt"</string> + <string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index ff987ea2b7b7..8e87bc10c470 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Dobbelttrykk ved siden av en app for å flytte den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Greit"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vis for å få mer informasjon."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimer"</string> + <string name="close_button_text" msgid="2913281996024033299">"Lukk"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index af91b36364f5..62587e58edc9 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਅੱਗੇ ਡਬਲ ਟੈਪ ਕਰੋ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ਸਮਝ ਲਿਆ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵਿਸਤਾਰ ਕਰੋ।"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"ਵੱਡਾ ਕਰੋ"</string> + <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index 8c6a4d55d269..363c851ca4cd 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Kliknij dwukrotnie obok aplikacji, aby ją przenieść"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozwiń, aby wyświetlić więcej informacji."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksymalizuj"</string> + <string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index 2fe448bcaf28..67369b8b0175 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Toque duas vezes junto a uma app para a reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expandir para obter mais informações"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> + <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index b8c9b54904a2..1f8cba85c9eb 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"එය නැවත ස්ථානගත කිරීමට යෙදුමකට යාබදව දෙවරක් තට්ටු කරන්න"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"තේරුණා"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"වැඩිදුර තොරතුරු සඳහා දිග හරින්න"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"විහිදන්න"</string> + <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index a9b9a58fcae3..591f4b71b00c 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Trokit dy herë pranë një aplikacioni për ta ripozicionuar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Zgjeroje për më shumë informacion."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizo"</string> + <string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index d58b1e3cafef..54384ca14db9 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Tryck snabbt två gånger bredvid en app för att flytta den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Utöka för mer information."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Utöka"</string> + <string name="close_button_text" msgid="2913281996024033299">"Stäng"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 331004aaf109..2f7d2246f939 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Gusa mara mbili karibu na programu ili uihamishe"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Nimeelewa"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Panua ili upate maelezo zaidi."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Panua"</string> + <string name="close_button_text" msgid="2913281996024033299">"Funga"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 9f1a97347d78..f0803507b5fc 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"యాప్ స్థానాన్ని మార్చడానికి దాని పక్కన డబుల్-ట్యాప్ చేయండి"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"అర్థమైంది"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"మరింత సమాచారం కోసం విస్తరించండి."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"గరిష్టీకరించండి"</string> + <string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 0a7fc9617e8f..bfae45afeb5d 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Mag-double tap sa tabi ng isang app para iposisyon ito ulit"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"I-expand para sa higit pang impormasyon."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"I-maximize"</string> + <string name="close_button_text" msgid="2913281996024033299">"Isara"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index b437392ca796..6a9be8048505 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Yeniden konumlandırmak için uygulamanın yanına iki kez dokunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Daha fazla bilgi için genişletin."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Ekranı Kapla"</string> + <string name="close_button_text" msgid="2913281996024033299">"Kapat"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index 5a7395c237bf..52f6d1145245 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"Щоб перемістити додаток, двічі торкніться області поруч із ним"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Розгорніть, щоб дізнатися більше."</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"Збільшити"</string> + <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index e6dc030e5fb2..3abfb0d4fa65 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس کے آگے دو بار تھپتھپائیں"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"سمجھ آ گئی"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"مزید معلومات کے لیے پھیلائیں۔"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"بڑا کریں"</string> + <string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index 15bb2939406b..8fed6bfb3eed 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -82,8 +82,6 @@ <string name="letterbox_education_reposition_text" msgid="1068293354123934727">"在某个应用旁边连续点按两次,即可调整它的位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展开即可了解详情。"</string> - <!-- no translation found for maximize_button_text (1650859196290301963) --> - <skip /> - <!-- no translation found for close_button_text (2913281996024033299) --> - <skip /> + <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> + <string name="close_button_text" msgid="2913281996024033299">"关闭"</string> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index e71a59d26740..8c0affb0a432 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -31,13 +31,15 @@ public interface BackAnimation { /** * Called when a {@link MotionEvent} is generated by a back gesture. * - * @param event the original {@link MotionEvent} - * @param action the original {@link KeyEvent#getAction()} when the event was dispatched to + * @param touchX the X touch position of the {@link MotionEvent}. + * @param touchY the Y touch position of the {@link MotionEvent}. + * @param keyAction the original {@link KeyEvent#getAction()} when the event was dispatched to * the process. This is forwarded separately because the input pipeline may mutate * the {#event} action state later. * @param swipeEdge the edge from which the swipe begins. */ - void onBackMotion(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge); + void onBackMotion(float touchX, float touchY, int keyAction, + @BackEvent.SwipeEdge int swipeEdge); /** * Sets whether the back gesture is past the trigger threshold or not. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 0cb56d72004d..0cf2b28921e1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -184,8 +184,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Override public void onBackMotion( - MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) { - mShellExecutor.execute(() -> onMotionEvent(event, action, swipeEdge)); + float touchX, float touchY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { + mShellExecutor.execute(() -> onMotionEvent(touchX, touchY, keyAction, swipeEdge)); } @Override @@ -256,33 +256,34 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} */ - public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) { + public void onMotionEvent(float touchX, float touchY, int keyAction, + @BackEvent.SwipeEdge int swipeEdge) { if (mTransitionInProgress) { return; } - if (action == MotionEvent.ACTION_MOVE) { + if (keyAction == MotionEvent.ACTION_MOVE) { if (!mBackGestureStarted) { // Let the animation initialized here to make sure the onPointerDownOutsideFocus // could be happened when ACTION_DOWN, it may change the current focus that we // would access it when startBackNavigation. - initAnimation(event); + initAnimation(touchX, touchY); } - onMove(event, swipeEdge); - } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + onMove(touchX, touchY, swipeEdge); + } else if (keyAction == MotionEvent.ACTION_UP || keyAction == MotionEvent.ACTION_CANCEL) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, - "Finishing gesture with event action: %d", action); + "Finishing gesture with event action: %d", keyAction); onGestureFinished(); } } - private void initAnimation(MotionEvent event) { + private void initAnimation(float touchX, float touchY) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "initAnimation mMotionStarted=%b", mBackGestureStarted); if (mBackGestureStarted || mBackNavigationInfo != null) { Log.e(TAG, "Animation is being initialized but is already started."); finishAnimation(); } - mInitTouchLocation.set(event.getX(), event.getY()); + mInitTouchLocation.set(touchX, touchY); mBackGestureStarted = true; try { @@ -351,18 +352,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTransaction.setVisibility(screenshotSurface, true); } - private void onMove(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge) { + private void onMove(float touchX, float touchY, @BackEvent.SwipeEdge int swipeEdge) { if (!mBackGestureStarted || mBackNavigationInfo == null) { return; } - int deltaX = Math.round(event.getX() - mInitTouchLocation.x); + int deltaX = Math.round(touchX - mInitTouchLocation.x); float progressThreshold = PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold; float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1); int backType = mBackNavigationInfo.getType(); RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget(); BackEvent backEvent = new BackEvent( - event.getX(), event.getY(), progress, swipeEdge, animationTarget); + touchX, touchY, progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index 920dcc70ad46..c962de67a93b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -35,6 +35,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.app.ActivityManager; @@ -78,6 +79,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange public static final int PARALLAX_DISMISSING = 1; public static final int PARALLAX_ALIGN_CENTER = 2; + private static final int FLING_ANIMATION_DURATION = 250; + private final int mDividerWindowWidth; private final int mDividerInsets; private final int mDividerSize; @@ -85,7 +88,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange private final Rect mTempRect = new Rect(); private final Rect mRootBounds = new Rect(); private final Rect mDividerBounds = new Rect(); + // Bounds1 final position should be always at top or left private final Rect mBounds1 = new Rect(); + // Bounds2 final position should be always at bottom or right private final Rect mBounds2 = new Rect(); private final Rect mWinBounds1 = new Rect(); private final Rect mWinBounds2 = new Rect(); @@ -275,28 +280,35 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange updateBounds(mDividePosition); } - /** Updates recording bounds of divider window and both of the splits. */ private void updateBounds(int position) { - mDividerBounds.set(mRootBounds); - mBounds1.set(mRootBounds); - mBounds2.set(mRootBounds); + updateBounds(position, mBounds1, mBounds2, mDividerBounds, true /* setEffectBounds */); + } + + /** Updates recording bounds of divider window and both of the splits. */ + private void updateBounds(int position, Rect bounds1, Rect bounds2, Rect dividerBounds, + boolean setEffectBounds) { + dividerBounds.set(mRootBounds); + bounds1.set(mRootBounds); + bounds2.set(mRootBounds); final boolean isLandscape = isLandscape(mRootBounds); if (isLandscape) { position += mRootBounds.left; - mDividerBounds.left = position - mDividerInsets; - mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth; - mBounds1.right = position; - mBounds2.left = mBounds1.right + mDividerSize; + dividerBounds.left = position - mDividerInsets; + dividerBounds.right = dividerBounds.left + mDividerWindowWidth; + bounds1.right = position; + bounds2.left = bounds1.right + mDividerSize; } else { position += mRootBounds.top; - mDividerBounds.top = position - mDividerInsets; - mDividerBounds.bottom = mDividerBounds.top + mDividerWindowWidth; - mBounds1.bottom = position; - mBounds2.top = mBounds1.bottom + mDividerSize; + dividerBounds.top = position - mDividerInsets; + dividerBounds.bottom = dividerBounds.top + mDividerWindowWidth; + bounds1.bottom = position; + bounds2.top = bounds1.bottom + mDividerSize; + } + DockedDividerUtils.sanitizeStackBounds(bounds1, true /** topLeft */); + DockedDividerUtils.sanitizeStackBounds(bounds2, false /** topLeft */); + if (setEffectBounds) { + mSurfaceEffectPolicy.applyDividerPosition(position, isLandscape); } - DockedDividerUtils.sanitizeStackBounds(mBounds1, true /** topLeft */); - DockedDividerUtils.sanitizeStackBounds(mBounds2, false /** topLeft */); - mSurfaceEffectPolicy.applyDividerPosition(position, isLandscape); } /** Inflates {@link DividerView} on the root surface. */ @@ -458,7 +470,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } ValueAnimator animator = ValueAnimator .ofInt(from, to) - .setDuration(250); + .setDuration(FLING_ANIMATION_DURATION); animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); animator.addUpdateListener( animation -> updateDivideBounds((int) animation.getAnimatedValue())); @@ -480,6 +492,86 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange animator.start(); } + /** Swich both surface position with animation. */ + public void splitSwitching(SurfaceControl.Transaction t, SurfaceControl leash1, + SurfaceControl leash2, Runnable finishCallback) { + final boolean isLandscape = isLandscape(); + final Rect insets = getDisplayInsets(mContext); + insets.set(isLandscape ? insets.left : 0, isLandscape ? 0 : insets.top, + isLandscape ? insets.right : 0, isLandscape ? 0 : insets.bottom); + + final int dividerPos = mDividerSnapAlgorithm.calculateNonDismissingSnapTarget( + isLandscape ? mBounds2.width() : mBounds2.height()).position; + final Rect distBounds1 = new Rect(); + final Rect distBounds2 = new Rect(); + final Rect distDividerBounds = new Rect(); + // Compute dist bounds. + updateBounds(dividerPos, distBounds2, distBounds1, distDividerBounds, + false /* setEffectBounds */); + // Offset to real position under root container. + distBounds1.offset(-mRootBounds.left, -mRootBounds.top); + distBounds2.offset(-mRootBounds.left, -mRootBounds.top); + distDividerBounds.offset(-mRootBounds.left, -mRootBounds.top); + // DO NOT move to insets area for smooth animation. + distBounds1.set(distBounds1.left, distBounds1.top, + distBounds1.right - insets.right, distBounds1.bottom - insets.bottom); + distBounds2.set(distBounds2.left + insets.left, distBounds2.top + insets.top, + distBounds2.right, distBounds2.bottom); + + ValueAnimator animator1 = moveSurface(t, leash1, getRefBounds1(), distBounds1, + false /* alignStart */); + ValueAnimator animator2 = moveSurface(t, leash2, getRefBounds2(), distBounds2, + true /* alignStart */); + ValueAnimator animator3 = moveSurface(t, getDividerLeash(), getRefDividerBounds(), + distDividerBounds, true /* alignStart */); + + AnimatorSet set = new AnimatorSet(); + set.playTogether(animator1, animator2, animator3); + set.setDuration(FLING_ANIMATION_DURATION); + set.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDividePosition = dividerPos; + updateBounds(mDividePosition); + finishCallback.run(); + } + }); + set.start(); + } + + private ValueAnimator moveSurface(SurfaceControl.Transaction t, SurfaceControl leash, + Rect start, Rect end, boolean alignStart) { + Rect tempStart = new Rect(start); + Rect tempEnd = new Rect(end); + final float diffX = tempEnd.left - tempStart.left; + final float diffY = tempEnd.top - tempStart.top; + final float diffWidth = tempEnd.width() - tempStart.width(); + final float diffHeight = tempEnd.height() - tempStart.height(); + ValueAnimator animator = ValueAnimator.ofFloat(0, 1); + animator.addUpdateListener(animation -> { + if (leash == null) return; + + final float scale = (float) animation.getAnimatedValue(); + final float distX = tempStart.left + scale * diffX; + final float distY = tempStart.top + scale * diffY; + final int width = (int) (tempStart.width() + scale * diffWidth); + final int height = (int) (tempStart.height() + scale * diffHeight); + if (alignStart) { + t.setPosition(leash, distX, distY); + t.setWindowCrop(leash, width, height); + } else { + final int offsetX = width - start.width(); + final int offsetY = height - start.height(); + t.setPosition(leash, distX + offsetX, distY + offsetY); + mTempRect.set(0, 0, width, height); + mTempRect.offsetTo(-offsetX, -offsetY); + t.setCrop(leash, mTempRect); + } + t.apply(); + }); + return animator; + } + private static Rect getDisplayInsets(Context context) { return context.getSystemService(WindowManager.class) .getMaximumWindowMetrics() diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 1e369899e354..a8c1071eb69e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -68,15 +68,15 @@ import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.transition.Transitions; -import com.android.wm.shell.unfold.UnfoldAnimationController; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; +import com.android.wm.shell.unfold.UnfoldAnimationController; import com.android.wm.shell.unfold.UnfoldBackgroundController; import com.android.wm.shell.unfold.UnfoldTransitionHandler; import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import com.android.wm.shell.unfold.animation.UnfoldTaskAnimator; -import com.android.wm.shell.unfold.qualifier.UnfoldTransition; import com.android.wm.shell.unfold.qualifier.UnfoldShellTransition; +import com.android.wm.shell.unfold.qualifier.UnfoldTransition; import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel; import com.android.wm.shell.windowdecor.WindowDecorViewModel; @@ -218,6 +218,7 @@ public abstract class WMShellModule { PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState, PipMotionHelper pipMotionHelper, PipMediaController pipMediaController, PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer, + PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController, WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, @@ -227,7 +228,7 @@ public abstract class WMShellModule { return Optional.ofNullable(PipController.create(context, displayController, pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, - pipMediaController, phonePipMenuController, pipTaskOrganizer, + pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, oneHandedController, mainExecutor)); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java index 3b3091a9caf3..bbc47e47afc5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java @@ -86,12 +86,12 @@ public interface Pip { } /** - * Registers the pinned stack animation listener. + * Set the callback when {@link PipTaskOrganizer#isInPip()} state is changed. * - * @param callback The callback of pinned stack animation. + * @param callback The callback accepts the result of {@link PipTaskOrganizer#isInPip()} + * when it's changed. */ - default void setPinnedStackAnimationListener(Consumer<Boolean> callback) { - } + default void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {} /** * Set the pinned stack with {@link PipAnimationController.AnimationType} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java index 85e56b7dd99f..1a4be3b41911 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java @@ -17,12 +17,15 @@ package com.android.wm.shell.pip; import android.annotation.IntDef; +import android.annotation.NonNull; import android.app.PictureInPictureParams; import android.content.ComponentName; import android.content.pm.ActivityInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; /** * Used to keep track of PiP leash state as it appears and animates by {@link PipTaskOrganizer} and @@ -37,6 +40,9 @@ public class PipTransitionState { public static final int ENTERED_PIP = 4; public static final int EXITING_PIP = 5; + private final List<OnPipTransitionStateChangedListener> mOnPipTransitionStateChangedListeners = + new ArrayList<>(); + /** * If set to {@code true}, no entering PiP transition would be kicked off and most likely * it's due to the fact that Launcher is handling the transition directly when swiping @@ -65,7 +71,13 @@ public class PipTransitionState { } public void setTransitionState(@TransitionState int state) { - mState = state; + if (mState != state) { + for (int i = 0; i < mOnPipTransitionStateChangedListeners.size(); i++) { + mOnPipTransitionStateChangedListeners.get(i).onPipTransitionStateChanged( + mState, state); + } + mState = state; + } } public @TransitionState int getTransitionState() { @@ -73,8 +85,7 @@ public class PipTransitionState { } public boolean isInPip() { - return mState >= TASK_APPEARED - && mState != EXITING_PIP; + return isInPip(mState); } public void setInSwipePipToHomeTransition(boolean inSwipePipToHomeTransition) { @@ -94,4 +105,23 @@ public class PipTransitionState { return mState < ENTERING_PIP || mState == EXITING_PIP; } + + public void addOnPipTransitionStateChangedListener( + @NonNull OnPipTransitionStateChangedListener listener) { + mOnPipTransitionStateChangedListeners.add(listener); + } + + public void removeOnPipTransitionStateChangedListener( + @NonNull OnPipTransitionStateChangedListener listener) { + mOnPipTransitionStateChangedListeners.remove(listener); + } + + public static boolean isInPip(@TransitionState int state) { + return state >= TASK_APPEARED && state != EXITING_PIP; + } + + public interface OnPipTransitionStateChangedListener { + void onPipTransitionStateChanged(@TransitionState int oldState, + @TransitionState int newState); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index c3e6d82df781..3000998f210d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -84,6 +84,7 @@ import com.android.wm.shell.pip.PipParamsChangedForwarder; import com.android.wm.shell.pip.PipSnapAlgorithm; import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.pip.PipTransitionState; import com.android.wm.shell.pip.PipUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.transition.Transitions; @@ -128,11 +129,14 @@ public class PipController implements PipTransitionController.PipTransitionCallb protected PhonePipMenuController mMenuController; protected PipTaskOrganizer mPipTaskOrganizer; + private PipTransitionState mPipTransitionState; protected PinnedStackListenerForwarder.PinnedTaskListener mPinnedTaskListener = new PipControllerPinnedTaskListener(); private boolean mIsKeyguardShowingOrAnimating; + private Consumer<Boolean> mOnIsInPipStateChangedListener; + private interface PipAnimationListener { /** * Notifies the listener that the Pip animation is started. @@ -291,6 +295,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState, PipMotionHelper pipMotionHelper, PipMediaController pipMediaController, PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer, + PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController, WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, @@ -305,7 +310,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController, - phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController, + phonePipMenuController, pipTaskOrganizer, pipTransitionState, + pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, oneHandedController, mainExecutor) .mImpl; @@ -321,6 +327,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb PipMediaController pipMediaController, PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer, + PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController, WindowManagerShellWrapper windowManagerShellWrapper, @@ -344,6 +351,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb mPipBoundsState = pipBoundsState; mPipMotionHelper = pipMotionHelper; mPipTaskOrganizer = pipTaskOrganizer; + mPipTransitionState = pipTransitionState; mMainExecutor = mainExecutor; mMediaController = pipMediaController; mMenuController = phonePipMenuController; @@ -370,6 +378,15 @@ public class PipController implements PipTransitionController.PipTransitionCallb onDisplayChanged(mDisplayController.getDisplayLayout(displayId), false /* saveRestoreSnapFraction */); }); + mPipTransitionState.addOnPipTransitionStateChangedListener((oldState, newState) -> { + if (mOnIsInPipStateChangedListener != null) { + final boolean wasInPip = PipTransitionState.isInPip(oldState); + final boolean nowInPip = PipTransitionState.isInPip(newState); + if (nowInPip != wasInPip) { + mOnIsInPipStateChangedListener.accept(nowInPip); + } + } + }); mPipBoundsState.setOnMinimalSizeChangeCallback( () -> { // The minimal size drives the normal bounds, so they need to be recalculated. @@ -664,6 +681,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb } } + private void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) { + mOnIsInPipStateChangedListener = callback; + if (mOnIsInPipStateChangedListener != null) { + callback.accept(mPipTransitionState.isInPip()); + } + } + private void setShelfHeightLocked(boolean visible, int height) { final int shelfHeight = visible ? height : 0; mPipBoundsState.setShelfVisibility(visible, shelfHeight); @@ -941,6 +965,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb } @Override + public void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) { + mMainExecutor.execute(() -> { + PipController.this.setOnIsInPipStateChangedListener(callback); + }); + } + + @Override public void setPinnedStackAnimationType(int animationType) { mMainExecutor.execute(() -> { PipController.this.setPinnedStackAnimationType(animationType); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index a68970591adc..6cfb700fc16a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -611,6 +611,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } + void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) { + if (mSideStagePosition == sideStagePosition) return; + SurfaceControl.Transaction t = mTransactionPool.acquire(); + final StageTaskListener topLeftStage = + mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage; + final StageTaskListener bottomRightStage = + mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage; + mSplitLayout.splitSwitching(t, topLeftStage.mRootLeash, bottomRightStage.mRootLeash, + () -> { + setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), + null /* wct */); + mTransactionPool.release(t); + }); + } + void setSideStagePosition(@SplitPosition int sideStagePosition, @Nullable WindowContainerTransaction wct) { setSideStagePosition(sideStagePosition, true /* updateBounds */, wct); @@ -1209,7 +1224,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onDoubleTappedDivider() { - setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), null /* wct */); + setSideStagePositionAnimated(SplitLayout.reversePosition(mSideStagePosition)); mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(), getSideStagePosition(), mSideStage.getTopChildTaskUid(), mSplitLayout.isLandscape()); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index 95bc579a4a51..0d309c1cc21a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -238,7 +238,8 @@ public class TaskSnapshotWindow { try { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#addToDisplay"); final int res = session.addToDisplay(window, layoutParams, View.GONE, displayId, - info.requestedVisibilities, tmpInputChannel, tmpInsetsState, tmpControls); + info.requestedVisibilities, tmpInputChannel, tmpInsetsState, tmpControls, + new Rect()); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (res < 0) { Slog.w(TAG, "Failed to add snapshot starting window res=" + res); @@ -260,8 +261,8 @@ public class TaskSnapshotWindow { tmpMergedConfiguration.getMergedConfiguration().windowConfiguration; windowLayout.computeFrames(layoutParams, tmpInsetsState, displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(), UNSPECIFIED_LENGTH, - UNSPECIFIED_LENGTH, info.requestedVisibilities, - null /* attachedWindowFrame */, 1f /* compatScale */, tmpFrames); + UNSPECIFIED_LENGTH, info.requestedVisibilities, 1f /* compatScale */, + tmpFrames); session.updateLayout(window, layoutParams, 0 /* flags */, tmpFrames, UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH); } else { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index fcfcbfa091db..e7c5cb2183db 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -298,7 +298,7 @@ public class BackAnimationControllerTest { private void doMotionEvent(int actionDown, int coordinate) { mController.onMotionEvent( - MotionEvent.obtain(0, mEventTime, actionDown, coordinate, coordinate, 0), + coordinate, coordinate, actionDown, BackEvent.EDGE_LEFT); mEventTime += 10; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index abd55dd7d606..babc9707ef9c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -53,6 +53,7 @@ import com.android.wm.shell.pip.PipParamsChangedForwarder; import com.android.wm.shell.pip.PipSnapAlgorithm; import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.pip.PipTransitionState; import org.junit.Before; import org.junit.Test; @@ -80,6 +81,7 @@ public class PipControllerTest extends ShellTestCase { @Mock private PipSnapAlgorithm mMockPipSnapAlgorithm; @Mock private PipMediaController mMockPipMediaController; @Mock private PipTaskOrganizer mMockPipTaskOrganizer; + @Mock private PipTransitionState mMockPipTransitionState; @Mock private PipTransitionController mMockPipTransitionController; @Mock private PipTouchHandler mMockPipTouchHandler; @Mock private PipMotionHelper mMockPipMotionHelper; @@ -104,8 +106,8 @@ public class PipControllerTest extends ShellTestCase { mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm, mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, - mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler, - mMockPipTransitionController, mMockWindowManagerShellWrapper, + mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState, + mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mPipParamsChangedForwarder, mMockOneHandedController, mMockExecutor); when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm); @@ -138,8 +140,8 @@ public class PipControllerTest extends ShellTestCase { mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm, mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, - mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler, - mMockPipTransitionController, mMockWindowManagerShellWrapper, + mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState, + mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mPipParamsChangedForwarder, mMockOneHandedController, mMockExecutor)); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index 630d0d2c827c..14d8ce4682c6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -249,7 +249,8 @@ public class StartingSurfaceDrawerTests { any() /* window */, any() /* attrs */, anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* requestedVisibility */, any() /* outInputChannel */, - any() /* outInsetsState */, any() /* outActiveControls */); + any() /* outInsetsState */, any() /* outActiveControls */, + any() /* outAttachedFrame */); TaskSnapshotWindow mockSnapshotWindow = TaskSnapshotWindow.create(windowInfo, mBinder, snapshot, mTestExecutor, () -> { diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java index 9976fa11d177..db5e52a44c8a 100644 --- a/media/java/android/media/MediaMetadata.java +++ b/media/java/android/media/MediaMetadata.java @@ -429,6 +429,15 @@ public final class MediaMetadata implements Parcelable { private MediaMetadata(Parcel in) { mBundle = in.readBundle(); mBitmapDimensionLimit = Math.max(in.readInt(), 1); + + // Proactively read bitmaps from known bitmap keys, to ensure that they're unparceled and + // added to mBundle's internal map. This ensures that the GC accounts for the underlying + // allocations, which it does not do if the bitmaps remain parceled (see b/215820910). + // TODO(b/223225532): Remove this workaround once the underlying allocations are properly + // tracked in NativeAllocationsRegistry. + getBitmap(METADATA_KEY_ART); + getBitmap(METADATA_KEY_ALBUM_ART); + getBitmap(METADATA_KEY_DISPLAY_ICON); } /** diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml index 318b60a50437..138386b0b8e6 100644 --- a/packages/CompanionDeviceManager/res/values-ar/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml @@ -18,8 +18,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string> <string name="confirmation_title" msgid="3785000297483688997">"السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> - <string name="profile_name_watch" msgid="576290739483672360">"ساعة"</string> - <string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> + <string name="profile_name_watch" msgid="576290739483672360">"الساعة"</string> + <string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديرها تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" msgid="3002344206574997652">"هذا التطبيق مطلوب لإدارة <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. سيتم السماح لتطبيق <xliff:g id="APP_NAME">%2$s</xliff:g> بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم وسجلّات المكالمات والأجهزة المجاورة."</string> <string name="permission_apps" msgid="6142133265286656158">"التطبيقات"</string> <string name="permission_apps_summary" msgid="798718816711515431">"بث تطبيقات هاتفك"</string> diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml index a5b642ac4dbc..0b6a195763c6 100644 --- a/packages/CompanionDeviceManager/res/values-de/strings.xml +++ b/packages/CompanionDeviceManager/res/values-de/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string> <string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, auf dein Gerät (<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>) zuzugreifen"</string> <string name="profile_name_watch" msgid="576290739483672360">"Smartwatch"</string> - <string name="chooser_title" msgid="2262294130493605839">"Gerät (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string> + <string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string> <string name="summary_watch" msgid="3002344206574997652">"Diese App wird zur Verwaltung des Geräts „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen für „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anrufliste“ und „Geräte in der Nähe“ zugreifen."</string> <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Smartphone-Apps streamen"</string> diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml index ee9384292161..54d13c4a42a9 100644 --- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string> <string name="confirmation_title" msgid="3785000297483688997">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a tu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string> - <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string> + <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string> <string name="summary_watch" msgid="3002344206574997652">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string> <string name="permission_apps" msgid="6142133265286656158">"Apps"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Transmitir las apps de tu teléfono"</string> diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml index e2fa97f2259c..beabaf1842bd 100644 --- a/packages/CompanionDeviceManager/res/values-fa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml @@ -39,7 +39,7 @@ <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string> <string name="summary_generic" msgid="2346762210105903720"></string> <string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string> - <string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string> + <string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string> <string name="consent_back" msgid="2560683030046918882">"برگشت"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"انتقال اجازههای برنامه به ساعت"</string> <string name="permission_sync_summary" msgid="8873391306499120778">"برای آسانتر کردن راهاندازی ساعت، برنامههای نصبشده در ساعت درحین راهاندازی از همان اجازههای تلفن استفاده خواهند کرد.\n\n ممکن است این اجازهها شامل دسترسی به میکروفون و مکان ساعت باشد."</string> diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml index b978af630a00..1b1727e8bc10 100644 --- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string> <string name="confirmation_title" msgid="3785000297483688997">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_watch" msgid="576290739483672360">"montre"</string> - <string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> + <string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" msgid="3002344206574997652">"Cette application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations suivantes : téléphone, messages texte, contacts, agenda, journaux d\'appels et appareils à proximité."</string> <string name="permission_apps" msgid="6142133265286656158">"Applications"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Diffusez les applications de votre téléphone"</string> diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml index 6ffe4b1ed3e8..30db3187857e 100644 --- a/packages/CompanionDeviceManager/res/values-fr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string> <string name="confirmation_title" msgid="3785000297483688997">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_watch" msgid="576290739483672360">"montre"</string> - <string name="chooser_title" msgid="2262294130493605839">"Sélectionner le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> + <string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" msgid="3002344206574997652">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts, à l\'agenda, aux journaux d\'appels et aux appareils à proximité."</string> <string name="permission_apps" msgid="6142133265286656158">"Applis"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Diffuser en streaming les applis de votre téléphone"</string> diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml index b23ac1019609..1ac399946cbe 100644 --- a/packages/CompanionDeviceManager/res/values-hi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string> <string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ऐक्सेस करने की अनुमति दें"</string> <string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string> - <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string> + <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से मैनेज किया जा सके"</string> <string name="summary_watch" msgid="3002344206574997652">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, इसे आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति मिल पाएगी."</string> <string name="permission_apps" msgid="6142133265286656158">"ऐप्लिकेशन"</string> <string name="permission_apps_summary" msgid="798718816711515431">"अपने फ़ोन के ऐप्लिकेशन को स्ट्रीम करें"</string> diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml index 88a1145234e2..0f7fb08c9da3 100644 --- a/packages/CompanionDeviceManager/res/values-it/strings.xml +++ b/packages/CompanionDeviceManager/res/values-it/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string> <string name="confirmation_title" msgid="3785000297483688997">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_watch" msgid="576290739483672360">"orologio"</string> - <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> che sia gestito da <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> + <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string> <string name="summary_watch" msgid="3002344206574997652">"Questa app è necessaria per gestire il tuo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. L\'app <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Calendar, Registri chiamate e Dispositivi nelle vicinanze."</string> <string name="permission_apps" msgid="6142133265286656158">"App"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Trasmetti in streaming le app del tuo telefono"</string> diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml index 3a345fbd20c5..d641f299d652 100644 --- a/packages/CompanionDeviceManager/res/values-ky/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml @@ -38,7 +38,7 @@ <string name="helper_summary_computer" msgid="1676407599909474428">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду тышкы экранга чыгарууга уруксат сурап жатат"</string> <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string> <string name="summary_generic" msgid="2346762210105903720"></string> - <string name="consent_yes" msgid="8344487259618762872">"Уруксат берүү"</string> + <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string> <string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string> <string name="consent_back" msgid="2560683030046918882">"Артка"</string> <string name="permission_sync_confirmation_title" msgid="667074294393493186">"Колдонмонун уруксаттарын саатка өткөрүү"</string> diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml index a20416f75714..f3bef4d97117 100644 --- a/packages/InputDevices/res/values-fi/strings.xml +++ b/packages/InputDevices/res/values-fi/strings.xml @@ -3,7 +3,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="8016145283189546017">"Syöttölaitteet"</string> <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android-näppäimistö"</string> - <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"englanti (Iso-Britannia)"</string> + <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"englanti (Yhdistynyt kuningaskunta)"</string> <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"englanti (Yhdysvallat)"</string> <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"englanti (Yhdysvallat), kansainvälinen"</string> <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"englanti (Yhdysvallat), Colemak"</string> diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml index 979de608736c..74f7d908120f 100644 --- a/packages/PackageInstaller/res/values-it/strings.xml +++ b/packages/PackageInstaller/res/values-it/strings.xml @@ -46,7 +46,7 @@ <string name="out_of_space_dlg_text" msgid="8727714096031856231">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera dello spazio e riprova."</string> <string name="app_not_found_dlg_title" msgid="5107924008597470285">"App non trovata"</string> <string name="app_not_found_dlg_text" msgid="5219983779377811611">"Impossibile trovare l\'applicazione nell\'elenco di applicazioni installate."</string> - <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Autorizzazione non concessa"</string> + <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Non autorizzate"</string> <string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"L\'utente corrente non è autorizzato a eseguire questa disinstallazione."</string> <string name="generic_error_dlg_title" msgid="5863195085927067752">"Errore"</string> <string name="generic_error_dlg_text" msgid="5287861443265795232">"Impossibile disinstallare l\'app."</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 0aa60e29c541..2919aa6528eb 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -628,7 +628,7 @@ <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> - <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string> + <string name="carrier_network_change_mode" msgid="4257621815706644026">"Carrier network changing"</string> <string name="data_connection_3g" msgid="931852552688157407">"3G"</string> <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string> <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string> diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml index 1bab7d8f186f..5f91d35bb31b 100644 --- a/packages/SettingsLib/res/values-pl/arrays.xml +++ b/packages/SettingsLib/res/values-pl/arrays.xml @@ -64,7 +64,7 @@ <item msgid="2779123106632690576">"Włączono"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> - <item msgid="6603880723315236832">"AVRCP 1.5 (domyślna)"</item> + <item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item> <item msgid="1637054408779685086">"AVRCP 1.3"</item> <item msgid="5896162189744596291">"AVRCP 1.4"</item> <item msgid="7556896992111771426">"AVRCP 1.6"</item> @@ -76,7 +76,7 @@ <item msgid="1963366694959681026">"avrcp16"</item> </string-array> <string-array name="bluetooth_map_versions"> - <item msgid="8786402640610987099">"MAP 1.2 (domyślny)"</item> + <item msgid="8786402640610987099">"MAP 1.2 (domyślnie)"</item> <item msgid="6817922176194686449">"MAP 1.3"</item> <item msgid="3423518690032737851">"MAP 1.4"</item> </string-array> @@ -86,7 +86,7 @@ <item msgid="8147982633566548515">"map14"</item> </string-array> <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="2494959071796102843">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="2494959071796102843">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="4055460186095649420">"SBC"</item> <item msgid="720249083677397051">"AAC"</item> <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> @@ -94,7 +94,7 @@ <item msgid="3825367753087348007">"LDAC"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="8868109554557331312">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="8868109554557331312">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="9024885861221697796">"SBC"</item> <item msgid="4688890470703790013">"AAC"</item> <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> @@ -102,38 +102,38 @@ <item msgid="2553206901068987657">"LDAC"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> - <item msgid="926809261293414607">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="926809261293414607">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="8003118270854840095">"44,1 kHz"</item> <item msgid="3208896645474529394">"48,0 kHz"</item> <item msgid="8420261949134022577">"88,2 kHz"</item> <item msgid="8887519571067543785">"96,0 kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> - <item msgid="2284090879080331090">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="2284090879080331090">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="1872276250541651186">"44,1 kHz"</item> <item msgid="8736780630001704004">"48,0 kHz"</item> <item msgid="7698585706868856888">"88,2 kHz"</item> <item msgid="8946330945963372966">"96,0 kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> - <item msgid="2574107108483219051">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="2574107108483219051">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="4671992321419011165">"16 bitów/próbkę"</item> <item msgid="1933898806184763940">"24 bity/próbkę"</item> <item msgid="1212577207279552119">"32 bity/próbkę"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> - <item msgid="9196208128729063711">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="9196208128729063711">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="1084497364516370912">"16 bitów/próbkę"</item> <item msgid="2077889391457961734">"24 bity/próbkę"</item> <item msgid="3836844909491316925">"32 bity/próbkę"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> - <item msgid="3014194562841654656">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="3014194562841654656">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="5982952342181788248">"Mono"</item> <item msgid="927546067692441494">"Stereo"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> - <item msgid="1997302811102880485">"Użyj wyboru systemu (domyślnie)"</item> + <item msgid="1997302811102880485">"Używaj wyboru systemu (domyślnie)"</item> <item msgid="8005696114958453588">"Mono"</item> <item msgid="1333279807604675720">"Stereo"</item> </string-array> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 860ee17f4a14..aec96a2f8ade 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -381,7 +381,7 @@ <string name="debug_layout_summary" msgid="8825829038287321978">"Pokazuj granice przycięcia, marginesy itd."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Układ od prawej do lewej"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Wymuszaj układ ekranu od prawej do lewej dla wszystkich języków"</string> - <string name="window_blurs" msgid="6831008984828425106">"Zezwól na rozmycie na poziomie okna"</string> + <string name="window_blurs" msgid="6831008984828425106">"Zezwalaj na rozmycie na poziomie okna"</string> <string name="force_msaa" msgid="4081288296137775550">"Wymuszaj 4x MSAA"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"Włączaj 4x MSAA w aplikacjach OpenGL ES 2.0"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"Debuguj operacje przycinania nieprostokątnego"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 3a6e58eff571..71eb1a818f56 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -371,7 +371,7 @@ <string name="show_hw_layers_updates" msgid="5268370750002509767">"Onyesha masasisho ya safu za maunzi"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Angaza kijani safu za maunzi zinaposasisha"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"Tatua uondoaji wa GPU"</string> - <string name="disable_overlays" msgid="4206590799671557143">"Lemaza miekeleo ya HW"</string> + <string name="disable_overlays" msgid="4206590799671557143">"Zima miekeleo ya HW"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"Daima tumia GPU kwa mchanganyiko wa skrini"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Kuiga nafasi ya rangi"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Wezesha ufuatiliaji wa OpenGL"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java index e8cbab8197b2..a040e28169e8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java @@ -32,7 +32,7 @@ public abstract class MediaManager { private static final String TAG = "MediaManager"; protected final Collection<MediaDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>(); - protected final List<MediaDevice> mMediaDevices = new ArrayList<>(); + protected final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); protected Context mContext; protected Notification mNotification; diff --git a/packages/SimAppDialog/res/values-en-rCA/strings.xml b/packages/SimAppDialog/res/values-en-rCA/strings.xml index 6236a8f64850..1ddbaf908d61 100644 --- a/packages/SimAppDialog/res/values-en-rCA/strings.xml +++ b/packages/SimAppDialog/res/values-en-rCA/strings.xml @@ -20,7 +20,7 @@ <string name="app_name" msgid="8898068901680117589">"Sim app dialogue"</string> <string name="install_carrier_app_title" msgid="334729104862562585">"Activate mobile service"</string> <string name="install_carrier_app_description" msgid="4014303558674923797">"To get your new SIM working properly, you\'ll need to install the <xliff:g id="ID_1">%1$s</xliff:g> app"</string> - <string name="install_carrier_app_description_default" msgid="7356830245205847840">"To get your new SIM working properly, you\'ll need to install the operator app"</string> + <string name="install_carrier_app_description_default" msgid="7356830245205847840">"To get your new SIM working properly, you\'ll need to install the carrier app"</string> <string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Not now"</string> <string name="install_carrier_app_download_action" msgid="7859229305958538064">"Download app"</string> </resources> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index ce0dda32146f..1c13b1660e31 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -723,7 +723,7 @@ android:excludeFromRecents="true" android:stateNotNeeded="true" android:resumeWhilePausing="true" - android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"> + android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"> <intent-filter> <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" /> <category android:name="android.intent.category.DEFAULT" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index 0f10589dfcf9..bd628ccb3c08 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -29,7 +29,7 @@ import java.lang.annotation.RetentionPolicy; /** * Interface that decides whether a touch on the phone was accidental. i.e. Pocket Dialing. * - * {@see com.android.systemui.classifier.FalsingManagerImpl} + * {@see com.android.systemui.classifier.BrightLineFalsingManager} */ @ProvidesInterface(version = FalsingManager.VERSION) public interface FalsingManager { diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index eba003fd6bd1..b1f5a3f9206f 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -84,7 +84,7 @@ <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"L\'administrador ha bloquejat el dispositiu"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositiu s\'ha bloquejat manualment"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No s\'ha reconegut"</string> - <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Per utilitzar Desbloqueig facial, activa l\'accés a la càmera a Configuració"</string> + <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Desbloqueig facial necessita accés a la càmera"</string> <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Introdueix el PIN de la SIM. Et queda # intent; si no l\'encertes, contacta amb l\'operador per desbloquejar el dispositiu.}other{Introdueix el PIN de la SIM. Et queden # intents.}}"</string> <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queda # intent; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador per obtenir informació.}other{La targeta SIM s\'ha desactivat. Introdueix el codi PUK per continuar. Et queden # intents; si no l\'encertes, la SIM no es podrà tornar a fer servir. Contacta amb l\'operador per obtenir informació.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Predeterminada"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index 05039d8a363b..9b4df35f1754 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -55,10 +55,10 @@ <string name="kg_wrong_pin" msgid="4160978845968732624">"Wrong PIN"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Try again in # second.}other{Try again in # seconds.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Enter SIM PIN."</string> - <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \'<xliff:g id="CARRIER">%1$s</xliff:g>\'."</string> + <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string> - <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string> - <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string> + <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string> + <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact carrier for details."</string> <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string> <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Confirm desired PIN code"</string> <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Unlocking SIM card…"</string> @@ -67,9 +67,9 @@ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string> - <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Incorrect SIM PIN code; you have # remaining attempt before you must contact your operator to unlock your device.}other{Incorrect SIM PIN code; you have # remaining attempts. }}"</string> - <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM is unusable. Contact your operator."</string> + <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Incorrect SIM PIN code you must now contact your carrier to unlock your device."</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Incorrect SIM PIN code, you have # remaining attempt before you must contact your carrier to unlock your device.}other{Incorrect SIM PIN code, you have # remaining attempts. }}"</string> + <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM is unusable. Contact your carrier."</string> <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Incorrect SIM PUK code; you have # remaining attempt before SIM becomes permanently unusable.}other{Incorrect SIM PUK code, you have # remaining attempts before SIM becomes permanently unusable.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN operation failed!"</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK operation failed!"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"To use Face Unlock, turn on camera access in Settings"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Enter SIM PIN. You have # remaining attempt before you must contact your operator to unlock your device.}other{Enter SIM PIN. You have # remaining attempts.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIM is now disabled. Enter PUK code to continue. You have # remaining attempt before SIM becomes permanently unusable. Contact operator for details.}other{SIM is now disabled. Enter PUK code to continue. You have # remaining attempts before SIM becomes permanently unusable. Contact operator for details.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Enter SIM PIN. You have # remaining attempt before you must contact your carrier to unlock your device.}other{Enter SIM PIN. You have # remaining attempts.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIM is now disabled. Enter PUK code to continue. You have # remaining attempt before SIM becomes permanently unusable. Contact carrier for details.}other{SIM is now disabled. Enter PUK code to continue. You have # remaining attempts before SIM becomes permanently unusable. Contact carrier for details.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogue"</string> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index 0932e93003f1..bf9491572cf8 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -84,7 +84,7 @@ <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratzaileak blokeatu egin du gailua"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Eskuz blokeatu da gailua"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ez da ezagutu"</string> - <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Aurpegi bidez desblokeatzeko eginbidea erabiltzeko, eman kamera atzitzeko baimena ezarpenetan"</string> + <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Aurpegi bidezko desblokeoak kamera atzitzeko baimena behar du"</string> <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Idatzi SIMaren PINa. # saiakera geratzen zaizu gailua desblokeatzeko operadorearekin harremanetan jarri behar izan aurretik.}other{Idatzi SIMaren PINa. # saiakera gelditzen zaizkizu.}}"</string> <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{Orain, SIMa desgaituta dago. Aurrera egiteko, idatzi PUK kodea. # saiakera geratzen zaizu SIMa betiko ez-erabilgarri geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.}other{Orain, SIMa desgaituta dago. Aurrera egiteko, idatzi PUK kodea. # saiakera geratzen zaizkizu SIMa betiko ez-erabilgarri geratu aurretik. Xehetasunak lortzeko, jarri operadorearekin harremanetan.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Lehenetsia"</string> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index cecc645bcd8a..b6ae96d1dea7 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -22,7 +22,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"మీ పిన్ని నమోదు చేయండి"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"మీ నమూనాను నమోదు చేయండి"</string> - <string name="keyguard_enter_your_password" msgid="7225626204122735501">"మీ పాస్వర్డ్ను నమోదు చేయండి"</string> + <string name="keyguard_enter_your_password" msgid="7225626204122735501">"మీ పాస్వర్డ్ను ఎంటర్ చేయండి"</string> <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"చెల్లని కార్డ్."</string> <string name="keyguard_charged" msgid="5478247181205188995">"ఛార్జ్ చేయబడింది"</string> <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వైర్ లేకుండా ఛార్జ్ అవుతోంది"</string> diff --git a/packages/SystemUI/res/layout/auth_biometric_background.xml b/packages/SystemUI/res/layout/auth_biometric_background.xml index 7ce81ad7f01b..995aea11ffc6 100644 --- a/packages/SystemUI/res/layout/auth_biometric_background.xml +++ b/packages/SystemUI/res/layout/auth_biometric_background.xml @@ -16,6 +16,8 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:theme="@style/Theme.AppCompat.DayNight" + android:background="?android:colorBackground" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" diff --git a/packages/SystemUI/res/layout/hybrid_conversation_notification.xml b/packages/SystemUI/res/layout/hybrid_conversation_notification.xml index 43b16618d615..a313833e2a66 100644 --- a/packages/SystemUI/res/layout/hybrid_conversation_notification.xml +++ b/packages/SystemUI/res/layout/hybrid_conversation_notification.xml @@ -57,7 +57,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - style="?attr/hybridNotificationTextStyle" + android:paddingEnd="4dp" + style="@*android:style/Widget.DeviceDefault.Notification.Text" /> <TextView @@ -65,6 +66,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - style="?attr/hybridNotificationTextStyle" + android:paddingEnd="4dp" + style="@*android:style/Widget.DeviceDefault.Notification.Text" /> </com.android.systemui.statusbar.notification.row.HybridConversationNotificationView> diff --git a/packages/SystemUI/res/layout/hybrid_notification.xml b/packages/SystemUI/res/layout/hybrid_notification.xml index e8d77511e53c..9ea7be50adec 100644 --- a/packages/SystemUI/res/layout/hybrid_notification.xml +++ b/packages/SystemUI/res/layout/hybrid_notification.xml @@ -20,19 +20,22 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="bottom|start" - style="?attr/hybridNotificationStyle"> + android:paddingStart="@*android:dimen/notification_content_margin_start" + android:paddingEnd="12dp"> <TextView android:id="@+id/notification_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" - style="?attr/hybridNotificationTitleStyle" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title" + android:paddingEnd="4dp" /> <TextView android:id="@+id/notification_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - style="?attr/hybridNotificationTextStyle" + android:paddingEnd="4dp" + style="@*android:style/Widget.DeviceDefault.Notification.Text" /> </com.android.systemui.statusbar.notification.row.HybridNotificationView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/media_ttt_chip.xml index 4d24140abbf4..d88680669fe0 100644 --- a/packages/SystemUI/res/layout/media_ttt_chip.xml +++ b/packages/SystemUI/res/layout/media_ttt_chip.xml @@ -31,6 +31,8 @@ android:padding="@dimen/media_ttt_chip_outer_padding" android:background="@drawable/media_ttt_chip_background" android:layout_marginTop="20dp" + android:layout_marginStart="@dimen/notification_side_paddings" + android:layout_marginEnd="@dimen/notification_side_paddings" android:clipToPadding="false" android:gravity="center_vertical" android:alpha="0.0" @@ -46,8 +48,9 @@ <TextView android:id="@+id/text" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_weight="1" android:textSize="@dimen/media_ttt_text_size" android:textColor="?android:attr/textColorPrimary" android:alpha="0.0" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 9bb3db9015c7..5b2edbc060bb 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Foon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Stembystand"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Beursie"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR-kodeskandeerder"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontsluit"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Toestel is gesluit"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Wys demonstrasiemodus"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Wekker"</string> - <string name="wallet_title" msgid="5369767670735827105">"Beursie"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Stel op om vinniger, veiliger aankope met jou foon te doen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Wys alles"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Tik om oop te maak"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 4627d3536ba7..3138bf966427 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"الكاميرا"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"الهاتف"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"المساعد الصوتي"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"المحفظة"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"محفظة"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"الماسح الضوئي لرمز الاستجابة السريعة"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"فتح القفل"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"الجهاز مُقفل."</string> @@ -403,8 +403,8 @@ <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات في ملفك الشخصي للعمل ولكن لا تتم مراقبتها في ملفك الشخصي."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. تظهر أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمشرف تكنولوجيا المعلومات."</string> - <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. تظهر أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمشرف تكنولوجيا المعلومات."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. تظهر أنشطة الشبكة في تطبيقات العمل، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمشرف تكنولوجيا المعلومات ومزوّد خدمة الشبكة الافتراضية الخاصة (VPN)."</string> + <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات رؤية أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات ومزوّد خدمة الشبكة الافتراضية الخاصة (VPN) رؤية أنشطة الشبكة في تطبيقات العمل، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"تطبيقاتك الشخصية متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. تظهر أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمزوّد خدمة الشبكة الافتراضية الخاصة (VPN)."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"فتح إعدادات الشبكة الافتراضية الخاصة (VPN)"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"عرض الوضع التجريبي"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string> <string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string> - <string name="wallet_title" msgid="5369767670735827105">"المحفظة"</string> + <string name="wallet_title" msgid="5369767670735827105">"محفظة"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"يمكنك إعداد طريقة دفع لإجراء عمليات شراء بسرعة وأمان أكبر باستخدام هاتفك."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"عرض الكل"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"انقر لفتح قفل الجهاز."</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index a0dc311e9181..2b6bd9a8c807 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -94,7 +94,7 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string> <string name="screenrecord_start_label" msgid="1750350278888217473">"Želite da započnete snimanje?"</string> <string name="screenrecord_description" msgid="1123231719680353736">"Tokom snimanja Android sistem može da snimi osetljive informacije koje su vidljive na ekranu ili koje se puštaju na uređaju. To obuhvata lozinke, informacije o plaćanju, slike, poruke i zvuk."</string> - <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimi zvuk"</string> + <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimaj zvuk"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk uređaja"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk sa uređaja, na primer, muzika, pozivi i melodije zvona"</string> <string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 46b0693242cd..8a8949182055 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"ক্যামেরা"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"ওয়ালেট"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR কোড স্ক্যানার"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index b9b1f6977b7f..ad7f10b5657f 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -373,7 +373,7 @@ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je vlasnik ovog uređaja i može nadzirati mrežni saobraćaj"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može nadzirati mrežni saobraćaj"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Ovaj uređaj pruža <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> - <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Ovaj uređaj pripada vašoj organizaciji i povezan je na internet putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Ovaj uređaj pripada vašoj organizaciji i povezan je s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je na internet putem aplikacije <xliff:g id="VPN_APP">%2$s</xliff:g>"</string> <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Ovaj uređaj pripada vašoj organizaciji"</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string> @@ -404,10 +404,10 @@ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Administrator je uključio zapisivanje na mreži, čime se nadzire saobraćaj na vašem radnom profilu, ali ne i na ličnom profilu."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Uređaj je povezan s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem IT administratoru."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Uređaj je povezan s internetom putem aplikacija <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Vaša mrežna aktivnost, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem IT administratoru."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Vaše poslovne aplikacije su povezane na internet putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost u poslovnim aplikacijama, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem IT administratoru i pružaocu VPN usluga."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Vaše poslovne aplikacije su povezane s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost u poslovnim aplikacijama, uključujući e-poštu i podatke o pregledanju, je vidljiva IT administratoru i pružaocu VPN usluga."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Lične aplikacije su povezane s internetom putem aplikacije <xliff:g id="VPN_APP">%1$s</xliff:g>. Vaša mrežna aktivnost, uključujući e-poštu i podatke o pregledanju, je vidljiva vašem pružaocu VPN usluga."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> - <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Otvorite postavke VPN mreže"</string> + <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Otvorite postavke VPN-a"</string> <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja tvoj roditelj. Roditelj može vidjeti i upravljati informacijama kao što su aplikacije koje koristiš, lokacija i vrijeme korištenja uređaja."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Pouzdani agent sprečava zaključavanje"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b19716980885..f7441f34073a 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Càmera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Telèfon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistència per veu"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escàner de codis QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloqueja"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositiu bloquejat"</string> @@ -403,8 +403,8 @@ <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"L\'administrador ha activat el registre de xarxa, que monitora el trànsit al teu perfil de treball, però no al personal."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI pot veure l\'activitat de la teva xarxa, inclosos els correus electrònics i les dades de navegació."</string> - <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. El teu administrador de TI pot veure l\'activitat de la teva xarxa, inclosos els correus electrònics i les dades de navegació."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Les aplicacions de treball es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI i el teu proveïdor de VPN poden veure l\'activitat de la teva xarxa en aplicacions de treball, inclosos els correus electrònics i les dades de navegació."</string> + <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Aquest dispositiu es connecta a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>. El teu administrador de TI pot veure la teva activitat a la xarxa, inclosos els correus electrònics i les dades de navegació."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Les aplicacions de treball es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu administrador de TI i el teu proveïdor de VPN poden veure la teva activitat a la xarxa en aplicacions de treball, inclosos els correus electrònics i les dades de navegació."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Les aplicacions personals es connecten a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. El teu proveïdor de VPN pot veure l\'activitat de la teva xarxa, inclosos els correus electrònics i les dades de navegació."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Obre la configuració de la VPN"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index cb9106f56781..169e475ddc49 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demomodus anzeigen"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Weckruf"</string> - <string name="wallet_title" msgid="5369767670735827105">"Geldbörse"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Füge eine Zahlungsmethode hinzu, um noch schneller und sicherer mit deinem Smartphone zu bezahlen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Alle anzeigen"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Zum Öffnen tippen"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index b469b45dd7ce..0519c96dd306 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -77,7 +77,7 @@ <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="7232739948999195960">"Can\'t save screenshot"</string> - <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> + <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organization"</string> <string name="screenshot_blocked_by_admin" msgid="5486757604822795797">"Taking screenshots is blocked by your IT admin"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Edit"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Edit screenshot"</string> @@ -322,7 +322,7 @@ </string-array> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> - <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> + <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="do_financed_disclosure_with_name" msgid="6723004643314467864">"This device is provided by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Swipe from icon for phone"</string> @@ -370,16 +370,16 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Start now"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string> - <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organisation owns this device and may monitor network traffic"</string> + <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organization owns this device and may monitor network traffic"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"This device is provided by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> - <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"This device belongs to your organisation and is connected to the Internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"This device belongs to your organization and is connected to the internet through <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the Internet through <xliff:g id="VPN_APP">%2$s</xliff:g>"</string> - <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"This device belongs to your organisation"</string> + <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"This device belongs to your organization"</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string> - <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"This device belongs to your organisation and is connected to the Internet through VPNs"</string> + <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"This device belongs to your organization and is connected to the internet through VPNs"</string> <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> and is connected to the Internet through VPNs"</string> - <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Your organisation may monitor network traffic in your work profile"</string> + <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Your organization may monitor network traffic in your work profile"</string> <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> may monitor network traffic in your work profile"</string> <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Work profile network activity is visible to your IT admin"</string> <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Network may be monitored"</string> @@ -396,9 +396,9 @@ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string> <string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string> <string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps and change this device\'s settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string> - <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string> - <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string> - <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string> + <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organization.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string> + <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organization installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string> + <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organization installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string> <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string> <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Your admin has turned on network logging, which monitors traffic on your device."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile."</string> @@ -709,7 +709,7 @@ <string name="running_foreground_services_msg" msgid="3009459259222695385">"Tap for details on battery and data usage"</string> <string name="mobile_data_disable_title" msgid="5366476131671617790">"Turn off mobile data?"</string> <string name="mobile_data_disable_message" msgid="8604966027899770415">"You won\'t have access to data or the Internet through <xliff:g id="CARRIER">%s</xliff:g>. Internet will only be available via Wi-Fi."</string> - <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your operator"</string> + <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"your carrier"</string> <string name="touch_filtered_warning" msgid="8119511393338714836">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> <string name="slice_permission_title" msgid="3262615140094151017">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string> <string name="slice_permission_text_1" msgid="6675965177075443714">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index d96d61ba3b99..c759542bdc66 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Cámara"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Billetera"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Escáner de código QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Ver en modo de demostración"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"Billetera"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepárate para realizar compras rápidas y seguras con tu teléfono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Presiona para abrir"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 9206f70550eb..aff899870990 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -404,7 +404,7 @@ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Tu administrador ha activado el registro de la red, por lo que se monitorizará el tráfico de tu perfil de trabajo, aunque no el de tu perfil personal."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Este dispositivo está conectado a Internet a través de <xliff:g id="VPN_APP_0">%1$s</xliff:g> y <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu administrador de TI."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en estas aplicaciones, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Tus aplicaciones de trabajo están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red en las aplicaciones de trabajo, incluidos los correos electrónicos y los datos de navegación, es visible para tu administrador de TI y tu proveedor de VPN."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Tus aplicaciones personales están conectadas a Internet a través de <xliff:g id="VPN_APP">%1$s</xliff:g>. Tu actividad de red, como los correos electrónicos y los datos de navegación, es visible para tu proveedor de VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir ajustes de VPN"</string> diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml index 36a542a5ad67..d3e7c8b762de 100644 --- a/packages/SystemUI/res/values-es/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml @@ -64,7 +64,7 @@ <string-array name="tile_states_rotation"> <item msgid="4578491772376121579">"No disponible"</item> <item msgid="5776427577477729185">"Desactivada"</item> - <item msgid="7105052717007227415">"Activada"</item> + <item msgid="7105052717007227415">"Activado"</item> </string-array> <string-array name="tile_states_bt"> <item msgid="5330252067413512277">"No disponible"</item> @@ -89,7 +89,7 @@ <string-array name="tile_states_color_correction"> <item msgid="2840507878437297682">"No disponible"</item> <item msgid="1909756493418256167">"Desactivada"</item> - <item msgid="4531508423703413340">"Activada"</item> + <item msgid="4531508423703413340">"Activado"</item> </string-array> <string-array name="tile_states_inversion"> <item msgid="3638187931191394628">"No disponible"</item> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 38a66e7bb4b7..e11a16597dd2 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -373,7 +373,7 @@ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> - <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string> + <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"See seade kuulub teie organisatsioonile ja on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string> <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ja on internetiga rakenduse <xliff:g id="VPN_APP">%2$s</xliff:g> kaudu ühendatud"</string> <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"See seade kuulub teie organisatsioonile"</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string> @@ -383,8 +383,8 @@ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> võib jälgida võrguliiklust teie tööprofiilil"</string> <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"Tööprofiili võrgutegevused on teie IT-administraatorile nähtavad"</string> <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Võrku võidakse jälgida"</string> - <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on internetiga VPN-ide kaudu ühendatud"</string> - <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string> + <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"See seade on ühendatud internetiga VPN-ide kaudu"</string> + <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string> <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string> <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud"</string> <string name="monitoring_title_financed_device" msgid="3659962357973919387">"Selle seadme on andnud <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -403,8 +403,8 @@ <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Teie administraator lülitas sisse võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib liiklust teie võrguprofiilil, kuid mitte teie isiklikul profiilil."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"See seade on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string> - <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on internetiga rakenduse <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie töörakenduste võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie IT-administraatorile ning VPN-i teenusepakkujale."</string> + <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"See seade on ühendatud internetiga rakenduste <xliff:g id="VPN_APP_0">%1$s</xliff:g> ja <xliff:g id="VPN_APP_1">%2$s</xliff:g> kaudu. Teie võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Teie töörakendused on ühendatud internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu. Teie töörakenduste võrgutegevused (sealhulgas meilid ja sirvimisandmed) on nähtavad teie IT-administraatorile ning VPN-i teenusepakkujale."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Teie isiklikud rakendused on internetiga rakenduse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu ühendatud. Teie võrgutegevus, sealhulgas meilid ja sirvimisandmed, on nähtav teie VPN-i teenusepakkujale."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN-i seadete avamine"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index e325f7402618..35142b95f215 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonoa"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ahots-laguntza"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Zorroa"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Diru-zorroa"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR kodeen eskanerra"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desblokeatu"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Gailua blokeatuta dago"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Erakutsi demo modua"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"Diru-zorroa"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguratu erosketa bizkorrago eta seguruagoak egiteko telefonoarekin"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Erakutsi guztiak"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Irekitzeko, sakatu hau"</string> @@ -547,7 +547,7 @@ <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Ezkerrera"</string> <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Eskuinera"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Erdiratu"</string> - <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabuladorea"</string> + <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Zuriunea"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Sartu"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Atzera"</string> @@ -572,7 +572,7 @@ <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Atzera"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Lasterbideak"</string> - <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu teklatuaren diseinua"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikazioak"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Laguntzailea"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Arakatzailea"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index c4afda29a5a4..8719b00b17c1 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"دوربین"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"تلفن"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"دستیار صوتی"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"کیف پول"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"کدخوان پاسخسریع"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"باز کردن قفل"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"دستگاه قفل است"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"نمایش حالت نمایشی"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"اترنت"</string> <string name="status_bar_alarm" msgid="87160847643623352">"زنگ"</string> - <string name="wallet_title" msgid="5369767670735827105">"کیفپول"</string> + <string name="wallet_title" msgid="5369767670735827105">"کیف پول"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"برای خرید سریعتر و امنتر با تلفن، راهاندازی کنید"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"نمایش همه"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"برای باز کردن ضربه بزنید"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index e163049b0f40..815f0189dd01 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Appareil photo"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphoner"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Lecteur de code QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 2e2779ae6300..d385337a1a44 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"कैमरा"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट बटन"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"क्यूआर कोड स्कैनर"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"डेमो मोड दिखाएं"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ईथरनेट"</string> <string name="status_bar_alarm" msgid="87160847643623352">"अलार्म"</string> - <string name="wallet_title" msgid="5369767670735827105">"वॉलेट"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"फ़ोन के ज़रिए तेज़ी से और सुरक्षित तरीके से खरीदारी करने के लिए सेट अप करें"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"अनलॉक करने के लिए टैप करें"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 41a68c5fb42e..a707c63d2bee 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Տեսախցիկ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Հեռախոս"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ձայնային հուշումներ"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Դրամապանակ"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR կոդերի սկաներ"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ապակողպել"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Սարքը կողպված է"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Ցուցադրական ռեժիմի ցուցադրում"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Զարթուցիչ"</string> - <string name="wallet_title" msgid="5369767670735827105">"Դրամապանակ"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Վճարեք հեռախոսով՝ ավելի արագ և ապահով"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Ցույց տալ բոլորը"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Հպեք բացելու համար"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index c2be668bb418..e16fc15ec3d1 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Fotocamera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portafoglio"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Scanner codici QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Sblocca"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloccato"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostra modalità demo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Sveglia"</string> - <string name="wallet_title" msgid="5369767670735827105">"Portafoglio"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Imposta un metodo di pagamento per effettuare acquisti in modo più rapido e sicuro con il telefono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostra tutto"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Tocca per aprire"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 3d2ae11fe34c..406aea64e618 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"კამერა"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ტელეფონი"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ხმოვანი დახმარება"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"საფულე"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR კოდის სკანერი"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"განბლოკვა"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"მოწყობილობა ჩაკეტილია"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"დემო-რეჟიმის ჩვენება"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ეთერნეტი"</string> <string name="status_bar_alarm" msgid="87160847643623352">"მაღვიძარა"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"საფულე"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"დააყენეთ შესყიდვების თქვენი ტელეფონით უფრო სწრაფად და უსაფრთხოდ შესასრულებლად"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ყველას ჩვენება"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"შეეხეთ გასახსნელად"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 38d71d3dfbe9..4f5b7e05cf48 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дауыс көмекшісі"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Әмиян"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR кодын сканерлеу қолданбасы"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Бекітпесін ашу"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Құрылғы құлыпталды."</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Демо режимін көрсету"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Оятқыш"</string> - <string name="wallet_title" msgid="5369767670735827105">"Әмиян"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефоныңызбен бұрынғыдан да жылдам әрі қауіпсіз сатып алу үшін параметрлерді орнатыңыз."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Барлығын көрсету"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Ашу үшін түртіңіз"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 0a6567d8bd1b..a921cb94b7e2 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"ម៉ាស៊ីនថត"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ទូរសព្ទ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ជំនួយសំឡេង"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"កាបូប"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"កម្មវិធីស្កេនកូដ QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"ដោះសោ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"បានចាក់សោឧបករណ៍"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"បង្ហាញរបៀបសាកល្បង"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"អ៊ីសឺរណិត"</string> <string name="status_bar_alarm" msgid="87160847643623352">"ម៉ោងរោទ៍"</string> - <string name="wallet_title" msgid="5369767670735827105">"កាបូប"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ធ្វើការរៀបចំ ដើម្បីធ្វើការទិញកាន់តែលឿនជាងមុន សុវត្ថិភាពជាងមុន ដោយប្រើទូរសព្ទរបស់អ្នក"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"បង្ហាញទាំងអស់"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ចុចដើម្បីបើក"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 82412d0500d8..46fa9a4c4d7e 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"ಕ್ಯಾಮರಾ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"ವಾಲೆಟ್"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್ಲಾಕ್"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 7e42d2011c1c..47c26460b94e 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"카메라"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"전화"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"음성 지원"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"지갑"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"월렛"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 코드 스캐너"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"잠금 해제"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"기기 잠김"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"데모 모드 표시"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"이더넷"</string> <string name="status_bar_alarm" msgid="87160847643623352">"알람"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"월렛"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"설정하여 휴대전화로 더욱 빠르고 안전하게 구매하세요."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"모두 표시"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"탭하여 열기"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 321554ce2242..437708acefff 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -404,7 +404,7 @@ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Администраторуңуз жумуш профилиңиздеги трафикке көз салуу үчүн, тармактын таржымалын иштетип койду (жеке профилиңизден маалымат алынбайт)."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Бул түзмөк Интернетке <xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу туташып турат. Тармактагы аракеттериңиз, ошондой эле электрондук почтадагы жана серепчидеги нерселериңиз IT администраторуңузга көрүнүп турат."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Бул түзмөк Интернетке <xliff:g id="VPN_APP_0">%1$s</xliff:g> жана <xliff:g id="VPN_APP_1">%2$s</xliff:g> аркылуу туташып турат. Тармактагы аракеттериңиз, ошондой эле электрондук почтадагы жана серепчидеги нерселериңиз IT администраторуңузга көрүнүп турат."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Жумуш колдонмолоруңуз Интернетке <xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу туташып турушат. Жумуш колдонмолору аркылуу тармакта жасаган аракеттериңиз, ошондой эле электрондук почтадагы жана серепчидеги нерселериңиз VPN провайдерине көрүнүп турат."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Жумуш колдонмолоруңуз Интернетке <xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу туташып турушат. Тармакта жумуш колдонмолору аркылуу жасаган аракеттериңиз, ошондой эле электрондук почтадагы жана серепчидеги нерселериңиз IT администраторуңузга жана VPN провайдерине көрүнөт."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Жеке колдонмолоруңуз Интернетке <xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу туташып турушат. Тармактагы аракеттериңиз, ошондой эле электрондук почтадагы жана серепчидеги нерселериңиз VPN провайдерине көрүнүп турат."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN жөндөөлөрүн ачуу"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 239554d5b148..a1a242450f73 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -547,7 +547,7 @@ <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Pa kreisi"</string> <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Pa labi"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centrā"</string> - <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulēšanas taustiņš"</string> + <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Atstarpe"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Ievadīšanas taustiņš"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Atpakaļatkāpes taustiņš"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 808fc9f77ecb..5c1bf4afff13 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Камера"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помош"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Паричник"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Скенер на QR-кодови"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Отклучување"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Уредот е заклучен"</string> @@ -403,7 +403,7 @@ <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред."</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Вашиот администратор вклучил мрежна евиденција, што подразбира следење на сообраќајот во работниот, но не и во личниот профил."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Уредов е поврзан на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string> - <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор."</string> + <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Уредот е поврзан на интернет преку <xliff:g id="VPN_APP_0">%1$s</xliff:g> и <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Вашата мрежна активност, вклучително е-пораките и податоците од прелистување, е видлива за IT-администраторот."</string> <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Вашите работни апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот IT-администратор и давател на услуги за VPN."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Вашите лични апликации се поврзани на интернет преку <xliff:g id="VPN_APP">%1$s</xliff:g>. Вашата мрежна активност во работните апликации, вклучително е-пораките и податоците од прелистување, е видлива за вашиот давател на услуги за VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Прикажи демо-режим"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Етернет"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Аларм"</string> - <string name="wallet_title" msgid="5369767670735827105">"Паричник"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Поставете за да купувате побрзо и побезбедно преку вашиот телефон"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи ги сите"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Допрете за да отворите"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index ec3545d4ea70..e95197891ead 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"ക്യാമറ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്സ് സഹായം"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"വാലറ്റ്"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR കോഡ് സ്കാനർ"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"അണ്ലോക്ക് ചെയ്യുക"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ഉപകരണം ലോക്ക് ചെയ്തു"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ഡെമോ മോഡ് കാണിക്കുക"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ഇതർനെറ്റ്"</string> <string name="status_bar_alarm" msgid="87160847643623352">"അലാറം"</string> - <string name="wallet_title" msgid="5369767670735827105">"വാലറ്റ്"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"നിങ്ങളുടെ ഫോൺ ഉപയോഗിച്ച് വാങ്ങലുകൾ വേഗത്തിലും സുരക്ഷിതമായും നടത്താനുള്ള സജ്ജീകരണം നടത്തുക"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"എല്ലാം കാണിക്കുക"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"തുറക്കാൻ ടാപ്പ് ചെയ്യുക"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 4b7880fb242f..e85b3a01e8be 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Dompet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Pengimbas Kod QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Peranti dikunci"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 141ab2b8275e..0ca2cde2b9ef 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"ਕੈਮਰਾ"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ਫ਼ੋਨ ਕਰੋ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"ਵਾਲੇਟ"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR ਕੋਡ ਸਕੈਨਰ"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"ਅਣਲਾਕ ਕਰੋ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ਡੈਮੋ ਮੋਡ ਦੇਖੋ"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ਈਥਰਨੈਟ"</string> <string name="status_bar_alarm" msgid="87160847643623352">"ਅਲਾਰਮ"</string> - <string name="wallet_title" msgid="5369767670735827105">"ਵਾਲੇਟ"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ਆਪਣੇ ਫ਼ੋਨ ਨਾਲ ਜ਼ਿਆਦਾ ਤੇਜ਼ ਅਤੇ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਖਰੀਦਾਂ ਕਰਨ ਲਈ ਸੈੱਟਅੱਪ ਕਰੋ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ਸਭ ਦਿਖਾਓ"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 3f9cc55e3d03..88f9963615c4 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Cameră foto"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistent vocal"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portofel"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Scanner de coduri QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Deblocați"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispozitiv blocat"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Afișați modul demonstrativ"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarmă"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"Portofel"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configurați pentru a face achiziții mai rapide și mai sigure cu telefonul dvs."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Afișați-le pe toate"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Atingeți pentru a deschide"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index b98c12ca1408..3c0d8392f829 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"කැමරාව"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"දුරකථනය"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"හඬ සහාය"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"පසුම්බිය"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR කේත ස්කෑනරය"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"අඟුල අරින්න"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"උපාංගය අගුලු දමා ඇත"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ආදර්ශන ප්රකාරය පෙන්වන්න"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"එලාමය"</string> - <string name="wallet_title" msgid="5369767670735827105">"පසුම්බිය"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ඔබගේ දුරකථනය සමඟ වඩා වේගවත්, වඩා සුරක්ෂිත මිලදී ගැනීම් සිදු කිරීමට සූදානම් වන්න"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"සියල්ල පෙන්වන්න"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"විවෘත කිරීමට තට්ටු කරන්න"</string> @@ -547,7 +547,7 @@ <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"වම්"</string> <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"දකුණු"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"මැද"</string> - <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab යතුර"</string> + <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"ඉඩ යතුර"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter යතුර"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace යතුර"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 7917aded4c1d..15d31bd073f0 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -94,7 +94,7 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string> <string name="screenrecord_start_label" msgid="1750350278888217473">"Желите да започнете снимање?"</string> <string name="screenrecord_description" msgid="1123231719680353736">"Током снимања Android систем може да сними осетљиве информације које су видљиве на екрану или које се пуштају на уређају. То обухвата лозинке, информације о плаћању, слике, поруке и звук."</string> - <string name="screenrecord_audio_label" msgid="6183558856175159629">"Сними звук"</string> + <string name="screenrecord_audio_label" msgid="6183558856175159629">"Снимај звук"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук уређаја"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук са уређаја, на пример, музика, позиви и мелодије звона"</string> <string name="screenrecord_mic_label" msgid="2111264835791332350">"Микрофон"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 46738831aeb7..6c8e02f3de8e 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"Kamera"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"Simu"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Mapendekezo ya Sauti"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Pochi"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Kichanganuzi cha Msimbo wa QR"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Fungua"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Kifaa kimefungwa"</string> @@ -404,7 +404,7 @@ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni ambayo hufuatilia shughuli kwenye wasifu wako wa kazini ila si kwenye wasifu wako wa binafsi."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Kifaa hiki kimeunganishwa kwenye intaneti kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>. Shughuli zako za mtandaoni kwenye programu za kazini, ikijumuisha barua pepe na data ya kuvinjari, zinaonekana kwa msimamizi wako wa TEHAMA na mtoa huduma wa VPN."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Kifaa hiki kimeunganishwa kwenye intaneti kupitia <xliff:g id="VPN_APP_0">%1$s</xliff:g> na <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Shughuli zako za mtandaoni kwenye programu za kazini, ikijumuisha barua pepe na data ya kuvinjari, zinaonekana kwa msimamizi wako wa TEHAMA na mtoa huduma wa VPN."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Programu zako za kazini zimeunganishwa kwenye intaneti kupitia<xliff:g id="VPN_APP">%1$s</xliff:g>. Shughuli zako za mtandaoni kwenye programu za kazini, ikijumuisha barua pepe na data ya kuvinjari, zinaonekana kwa msimamizi wako TEHAMA na mtoa huduma wa VPN."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Programu zako za kazini zimeunganishwa kwenye intaneti kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>. Shughuli zako za mtandaoni kwenye programu za kazini, ikijumuisha barua pepe na data ya kuvinjari, zinaonekana kwa msimamizi wako TEHAMA na mtoa huduma wa VPN."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Programu zako binafsi zimeunganishwa kwenye intaneti kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>. Shughuli zako za mtandaoni kwenye programu za kazini, ikijumuisha barua pepe na data ya kuvinjari, zinaonekana kwa mtoa huduma wako wa VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Fungua mipangilio ya VPN"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Onyesha hali ya onyesho"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethaneti"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Kengele"</string> - <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> + <string name="wallet_title" msgid="5369767670735827105">"Pochi"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Weka njia ya kulipa ili uweze kununua kwa njia salama na haraka zaidi ukitumia simu yako"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Onyesha zote"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"Gusa ili ufungue"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index de44fecbf7fe..36767ea2d407 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"கேமரா"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ஃபோன்"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"குரல் உதவி"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"வாலட்"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR குறியீடு ஸ்கேனர்"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"அன்லாக் செய்"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"சாதனம் பூட்டப்பட்டுள்ளது"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"டெமோ முறையைக் காட்டு"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ஈதர்நெட்"</string> <string name="status_bar_alarm" msgid="87160847643623352">"அலாரம்"</string> - <string name="wallet_title" msgid="5369767670735827105">"வாலட்"</string> + <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"மொபைல் மூலம் விரைவாகவும் பாதுகாப்பாகவும் பர்ச்சேஸ்கள் செய்ய பேமெண்ட் முறையை அமைக்கவும்"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"அனைத்தையும் காட்டு"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"திறக்க தட்டவும்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 940303607612..4d124f5ed6e7 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"కెమెరా"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"వాలెట్"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR కోడ్ స్కానర్"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"అన్లాక్ చేయి"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string> @@ -515,7 +515,7 @@ <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్లను సపోర్ట్ చేయదు"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"ఈ నోటిఫికేషన్లను సవరించడం వీలుపడదు."</string> <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"కాల్ నోటిఫికేషన్లను ఎడిట్ చేయడం సాధ్యం కాదు."</string> - <string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్ల సమూహాన్ని ఇక్కడ కాన్ఫిగర్ చేయలేము"</string> + <string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్ల గ్రూప్ను ఇక్కడ కాన్ఫిగర్ చేయలేము"</string> <string name="notification_delegate_header" msgid="1264510071031479920">"ప్రాక్సీ చేయబడిన నోటిఫికేషన్"</string> <string name="notification_channel_dialog_title" msgid="6856514143093200019">"అన్ని <xliff:g id="APP_NAME">%1$s</xliff:g> నోటిఫికేషన్లు"</string> <string name="see_more_title" msgid="7409317011708185729">"మరిన్ని చూడండి"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 74affb608722..8daf4b58e747 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -373,7 +373,7 @@ <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"อุปกรณ์นี้ให้บริการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> - <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"อุปกรณ์นี้เป็นขององค์กรและเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"อุปกรณ์นี้เป็นของ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> และเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%2$s</xliff:g>"</string> <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string> @@ -403,8 +403,8 @@ <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในอุปกรณ์ของคุณ"</string> <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"ผู้ดูแลระบบได้เปิดการบันทึกกิจกรรมของเครือข่าย ซึ่งจะตรวจสอบการรับส่งข้อมูลในโปรไฟล์งานแต่ไม่ตรวจสอบในโปรไฟล์ส่วนตัวของคุณ"</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string> - <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP_0">%1$s</xliff:g> และ<xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่ายรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string> + <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"อุปกรณ์นี้เชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP_0">%1$s</xliff:g> และ <xliff:g id="VPN_APP_1">%2$s</xliff:g> ผู้ดูแลระบบไอทีสามารถดูกิจกรรมที่คุณทำในเครือข่าย ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"แอปงานเชื่อมต่ออินเทอร์เน็ตผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ดูแลระบบไอทีและผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายในแอปงานได้ ซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บ"</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"แอปส่วนตัวเชื่อมต่ออินเทอร์เน็ตผ่าน<xliff:g id="VPN_APP">%1$s</xliff:g> ผู้ให้บริการ VPN สามารถดูกิจกรรมที่คุณทำในเครือข่ายซึ่งรวมถึงอีเมลและข้อมูลการท่องเว็บได้"</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"เปิดการตั้งค่า VPN"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 9d62d655b4b1..7df433910076 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -404,7 +404,7 @@ <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Quản trị viên của bạn đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trong hồ sơ công việc chứ không giám sát lưu lượng truy cập trong hồ sơ cá nhân của bạn."</string> <string name="monitoring_description_named_vpn" msgid="7502657784155456414">"Thiết bị này được kết nối với Internet thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>. Hoạt động mạng bao gồm email và dữ liệu duyệt web sẽ được hiển thị cho quản trị viên CNTT."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Thiết bị này được kết nối với Internet thông qua <xliff:g id="VPN_APP_0">%1$s</xliff:g> và <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Hoạt động mạng bao gồm email và dữ liệu duyệt web sẽ được hiển thị cho quản trị viên CNTT."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Ứng dụng công việc của bạn được kết nối với Internet thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>. Hoạt động mạng trong các ứng dụng công việc, bao gồm email và dữ liệu duyệt web sẽ được hiển thị cho quản trị viên CNTT và nhà cung cấp VPN."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Ứng dụng công việc của bạn được kết nối với Internet thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>. Hoạt động mạng trong các ứng dụng công việc, bao gồm cả email và dữ liệu duyệt web, sẽ được hiển thị cho quản trị viên CNTT và nhà cung cấp VPN của bạn."</string> <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Ứng dụng cá nhân được kết nối với Internet thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>. Hoạt động mạng của bạn, bao gồm email và dữ liệu duyệt web, được hiển thị cho nhà cung cấp VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Mở phần cài đặt VPN"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 9db8645ed8f6..2ac494a20db5 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -118,7 +118,7 @@ <string name="accessibility_camera_button" msgid="2938898391716647247">"相機"</string> <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音助手"</string> - <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string> + <string name="accessibility_wallet_button" msgid="1458258783460555507">"錢包"</string> <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR 碼掃瞄器"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"解鎖"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已上鎖"</string> @@ -463,7 +463,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"以太網"</string> <string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string> - <string name="wallet_title" msgid="5369767670735827105">"電子錢包"</string> + <string name="wallet_title" msgid="5369767670735827105">"錢包"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"完成設定後即可透過手機更快速安全地購物"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string> <string name="wallet_secondary_label_no_card" msgid="8488069304491125713">"輕按即可開啟"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 45f67f6d8295..a0fe941eb5a6 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -547,7 +547,7 @@ <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"向左鍵"</string> <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"向右鍵"</string> <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"中央鍵"</string> - <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab 鍵"</string> + <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"空格鍵"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter 鍵"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace 鍵"</string> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 70a72ad23d7e..9a71995383ac 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -108,12 +108,6 @@ <attr name="android:layout" /> </declare-styleable> - <declare-styleable name="HybridNotificationTheme"> - <attr name="hybridNotificationStyle" format="reference" /> - <attr name="hybridNotificationTitleStyle" format="reference" /> - <attr name="hybridNotificationTextStyle" format="reference" /> - </declare-styleable> - <declare-styleable name="PluginInflateContainer"> <attr name="viewType" format="string" /> </declare-styleable> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 8b2481cff2a9..f954bc9bf17c 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -17,30 +17,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> - <!-- HybridNotification themes and styles --> - - <style name="HybridNotification"> - <item name="hybridNotificationStyle">@style/hybrid_notification</item> - <item name="hybridNotificationTitleStyle">@style/hybrid_notification_title</item> - <item name="hybridNotificationTextStyle">@style/hybrid_notification_text</item> - </style> - - <style name="hybrid_notification"> - <item name="android:paddingStart">@*android:dimen/notification_content_margin_start</item> - <item name="android:paddingEnd">12dp</item> - </style> - - <style name="hybrid_notification_title"> - <item name="android:paddingEnd">4dp</item> - <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault.Notification.Title</item> - </style> - - <style name="hybrid_notification_text" - parent="@*android:style/Widget.DeviceDefault.Notification.Text"> - <item name="android:paddingEnd">4dp</item> - </style> - - <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon"> <item name="android:textSize">@dimen/status_bar_clock_size</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index e9ac26182c7e..db416013c453 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -186,6 +186,8 @@ public class RemoteTransitionCompat implements Parcelable { } catch (RemoteException e) { Log.e(TAG, "Error merging transition.", e); } + // commit taskAppeared after merge transition finished. + mRecentsSession.commitTasksAppearedIfNeeded(recents); } }; mTransition = new RemoteTransition(remote, appThread); @@ -226,6 +228,7 @@ public class RemoteTransitionCompat implements Parcelable { private PictureInPictureSurfaceTransaction mPipTransaction = null; private IBinder mTransition = null; private boolean mKeyguardLocked = false; + private RemoteAnimationTargetCompat[] mAppearedTargets; void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info, IRemoteTransitionFinishedCallback finishCB, @@ -251,6 +254,7 @@ public class RemoteTransitionCompat implements Parcelable { boolean merge(TransitionInfo info, SurfaceControl.Transaction t, RecentsAnimationListener recents) { SparseArray<TransitionInfo.Change> openingTasks = null; + mAppearedTargets = null; boolean cancelRecents = false; boolean homeGoingAway = false; boolean hasChangingApp = false; @@ -331,10 +335,17 @@ public class RemoteTransitionCompat implements Parcelable { targets[i] = target; } t.apply(); - recents.onTasksAppeared(targets); + mAppearedTargets = targets; return true; } + private void commitTasksAppearedIfNeeded(RecentsAnimationListener recents) { + if (mAppearedTargets != null) { + recents.onTasksAppeared(mAppearedTargets); + mAppearedTargets = null; + } + } + @Override public ThumbnailData screenshotTask(int taskId) { try { final TaskSnapshot snapshot = diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 65c415b5272b..11519bf38516 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -375,10 +375,23 @@ public class KeyguardSecurityContainer extends FrameLayout { mViewMode.updatePositionByTouchX(x); } - /** Returns whether the inner SecurityViewFlipper is left-aligned when in one-handed mode. */ - public boolean isOneHandedModeLeftAligned() { - return mCurrentMode == MODE_ONE_HANDED - && ((OneHandedViewMode) mViewMode).isLeftAligned(); + public boolean isSidedSecurityMode() { + return mViewMode instanceof SidedSecurityMode; + } + + /** Returns whether the inner SecurityViewFlipper is left-aligned when in sided mode. */ + public boolean isSecurityLeftAligned() { + return mViewMode instanceof SidedSecurityMode + && ((SidedSecurityMode) mViewMode).isLeftAligned(); + } + + /** + * Returns whether the touch happened on the other side of security (like bouncer) when in + * sided mode. + */ + public boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev) { + return mViewMode instanceof SidedSecurityMode + && ((SidedSecurityMode) mViewMode).isTouchOnTheOtherSideOfSecurity(ev); } public void onPause() { @@ -437,12 +450,15 @@ public class KeyguardSecurityContainer extends FrameLayout { @Override public boolean onTouchEvent(MotionEvent event) { final int action = event.getActionMasked(); - mDoubleTapDetector.onTouchEvent(event); boolean result = mMotionEventListeners.stream() .anyMatch(listener -> listener.onTouchEvent(event)) || super.onTouchEvent(event); + // double tap detector should be called after listeners handle touches as listeners are + // helping with ignoring falsing. Otherwise falsing will be activated for some double taps + mDoubleTapDetector.onTouchEvent(event); + switch (action) { case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); @@ -487,11 +503,16 @@ public class KeyguardSecurityContainer extends FrameLayout { private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDoubleTap(MotionEvent e) { - if (!mIsDragging) { - mViewMode.handleDoubleTap(e); - } + return handleDoubleTap(e); + } + } + + @VisibleForTesting boolean handleDoubleTap(MotionEvent e) { + if (!mIsDragging) { + mViewMode.handleDoubleTap(e); return true; } + return false; } void addMotionEventListener(Gefingerpoken listener) { @@ -771,6 +792,70 @@ public class KeyguardSecurityContainer extends FrameLayout { } /** + * Base class for modes which support having on left/right side of the screen, used for large + * screen devices + */ + abstract static class SidedSecurityMode implements ViewMode { + private ViewGroup mView; + private GlobalSettings mGlobalSettings; + private int mDefaultSideSetting; + + public void init(ViewGroup v, GlobalSettings globalSettings, boolean leftAlignedByDefault) { + mView = v; + mGlobalSettings = globalSettings; + mDefaultSideSetting = + leftAlignedByDefault ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT + : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT; + } + + /** + * Determine if a double tap on this view is on the other side. If so, will animate + * positions and record the preference to always show on this side. + */ + @Override + public void handleDoubleTap(MotionEvent event) { + boolean currentlyLeftAligned = isLeftAligned(); + // Did the tap hit the "other" side of the bouncer? + if (isTouchOnTheOtherSideOfSecurity(event, currentlyLeftAligned)) { + boolean willBeLeftAligned = !currentlyLeftAligned; + updateSideSetting(willBeLeftAligned); + + int keyguardState = willBeLeftAligned + ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT + : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT; + SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState); + + updateSecurityViewLocation(willBeLeftAligned, /* animate= */ true); + } + } + + private boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev, boolean leftAligned) { + float x = ev.getX(); + return (leftAligned && (x > mView.getWidth() / 2f)) + || (!leftAligned && (x < mView.getWidth() / 2f)); + } + + public boolean isTouchOnTheOtherSideOfSecurity(MotionEvent ev) { + return isTouchOnTheOtherSideOfSecurity(ev, isLeftAligned()); + } + + protected abstract void updateSecurityViewLocation(boolean leftAlign, boolean animate); + + boolean isLeftAligned() { + return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, + mDefaultSideSetting) + == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT; + } + + protected void updateSideSetting(boolean leftAligned) { + mGlobalSettings.putInt( + Settings.Global.ONE_HANDED_KEYGUARD_SIDE, + leftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT + : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT); + } + } + + /** * Default bouncer is centered within the space */ static class DefaultViewMode implements ViewMode { @@ -802,7 +887,7 @@ public class KeyguardSecurityContainer extends FrameLayout { * User switcher mode will display both the current user icon as well as * a user switcher, in both portrait and landscape modes. */ - static class UserSwitcherViewMode implements ViewMode { + static class UserSwitcherViewMode extends SidedSecurityMode { private ViewGroup mView; private ViewGroup mUserSwitcherViewGroup; private KeyguardSecurityViewFlipper mViewFlipper; @@ -819,6 +904,7 @@ public class KeyguardSecurityContainer extends FrameLayout { @NonNull KeyguardSecurityViewFlipper viewFlipper, @NonNull FalsingManager falsingManager, @NonNull UserSwitcherController userSwitcherController) { + init(v, globalSettings, /* leftAlignedByDefault= */false); mView = v; mViewFlipper = viewFlipper; mFalsingManager = falsingManager; @@ -1030,6 +1116,10 @@ public class KeyguardSecurityContainer extends FrameLayout { @Override public void updateSecurityViewLocation() { + updateSecurityViewLocation(isLeftAligned(), /* animate= */false); + } + + public void updateSecurityViewLocation(boolean leftAlign, boolean animate) { int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans); if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { @@ -1039,8 +1129,12 @@ public class KeyguardSecurityContainer extends FrameLayout { mUserSwitcherViewGroup.setTranslationY(yTrans); mViewFlipper.setTranslationY(-yTrans); } else { - updateViewGravity(mViewFlipper, Gravity.RIGHT | Gravity.BOTTOM); - updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.CENTER_VERTICAL); + int securityHorizontalGravity = leftAlign ? Gravity.LEFT : Gravity.RIGHT; + int userSwitcherHorizontalGravity = + securityHorizontalGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT; + updateViewGravity(mViewFlipper, securityHorizontalGravity | Gravity.BOTTOM); + updateViewGravity(mUserSwitcherViewGroup, + userSwitcherHorizontalGravity | Gravity.CENTER_VERTICAL); // Attempt to reposition a bit higher to make up for this frame being a bit lower // on the device @@ -1060,20 +1154,19 @@ public class KeyguardSecurityContainer extends FrameLayout { * Logic to enabled one-handed bouncer mode. Supports animating the bouncer * between alternate sides of the display. */ - static class OneHandedViewMode implements ViewMode { + static class OneHandedViewMode extends SidedSecurityMode { @Nullable private ValueAnimator mRunningOneHandedAnimator; private ViewGroup mView; private KeyguardSecurityViewFlipper mViewFlipper; - private GlobalSettings mGlobalSettings; @Override public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings, @NonNull KeyguardSecurityViewFlipper viewFlipper, @NonNull FalsingManager falsingManager, @NonNull UserSwitcherController userSwitcherController) { + init(v, globalSettings, /* leftAlignedByDefault= */true); mView = v; mViewFlipper = viewFlipper; - mGlobalSettings = globalSettings; updateSecurityViewGravity(); updateSecurityViewLocation(isLeftAligned(), /* animate= */false); @@ -1107,43 +1200,6 @@ public class KeyguardSecurityContainer extends FrameLayout { updateSecurityViewLocation(isTouchOnLeft, /* animate= */false); } - boolean isLeftAligned() { - return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, - Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT) - == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT; - } - - private void updateSideSetting(boolean leftAligned) { - mGlobalSettings.putInt( - Settings.Global.ONE_HANDED_KEYGUARD_SIDE, - leftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT - : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT); - } - - /** - * Determine if a double tap on this view is on the other side. If so, will animate - * positions and record the preference to always show on this side. - */ - @Override - public void handleDoubleTap(MotionEvent event) { - float x = event.getX(); - boolean currentlyLeftAligned = isLeftAligned(); - // Did the tap hit the "other" side of the bouncer? - if ((currentlyLeftAligned && (x > mView.getWidth() / 2f)) - || (!currentlyLeftAligned && (x < mView.getWidth() / 2f))) { - - boolean willBeLeftAligned = !currentlyLeftAligned; - updateSideSetting(willBeLeftAligned); - - int keyguardState = willBeLeftAligned - ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT - : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT; - SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState); - - updateSecurityViewLocation(willBeLeftAligned, true /* animate */); - } - } - @Override public void updateSecurityViewLocation() { updateSecurityViewLocation(isLeftAligned(), /* animate= */false); @@ -1151,10 +1207,10 @@ public class KeyguardSecurityContainer extends FrameLayout { /** * Moves the inner security view to the correct location (in one handed mode) with - * animation. This is triggered when the user taps on the side of the screen that is not - * currently occupied by the security view. + * animation. This is triggered when the user double taps on the side of the screen that is + * not currently occupied by the security view. */ - private void updateSecurityViewLocation(boolean leftAlign, boolean animate) { + protected void updateSecurityViewLocation(boolean leftAlign, boolean animate) { if (mRunningOneHandedAnimator != null) { mRunningOneHandedAnimator.cancel(); mRunningOneHandedAnimator = null; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 19a2d9ed5b7b..61e262440607 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -116,12 +116,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard // If we're in one handed mode, the user can tap on the opposite side of the screen // to move the bouncer across. In that case, inhibit the falsing (otherwise the taps // to move the bouncer to each screen side can end up closing it instead). - if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { - boolean isLeftAligned = mView.isOneHandedModeLeftAligned(); - if ((isLeftAligned && ev.getX() > mView.getWidth() / 2f) - || (!isLeftAligned && ev.getX() <= mView.getWidth() / 2f)) { - mFalsingCollector.avoidGesture(); - } + if (mView.isTouchOnTheOtherSideOfSecurity(ev)) { + mFalsingCollector.avoidGesture(); } if (mTouchDown != null) { @@ -169,8 +165,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT; - if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { - bouncerSide = mView.isOneHandedModeLeftAligned() + if (mView.isSidedSecurityMode()) { + bouncerSide = mView.isSecurityLeftAligned() ? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT : SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT; } @@ -367,8 +363,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard public void onResume(int reason) { if (mCurrentSecurityMode != SecurityMode.None) { int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN; - if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) { - state = mView.isOneHandedModeLeftAligned() + if (mView.isSidedSecurityMode()) { + state = mView.isSecurityLeftAligned() ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT; } diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index b0530f825b9c..61b1b66338e8 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -52,15 +52,18 @@ class FaceScanningOverlay( private var cameraProtectionColor = Color.BLACK var faceScanningAnimColor = Utils.getColorAttrDefaultColor(context, com.android.systemui.R.attr.wallpaperTextColorAccent) + private var cameraProtectionAnimator: ValueAnimator? = null + var hideOverlayRunnable: Runnable? = null + + init { + visibility = View.INVISIBLE // only show this view when face scanning is happening + } override fun setColor(color: Int) { cameraProtectionColor = color invalidate() } - private var cameraProtectionAnimator: ValueAnimator? = null - var hideOverlayRunnable: Runnable? = null - override fun drawCutoutProtection(canvas: Canvas) { if (rimProgress > HIDDEN_RIM_SCALE && !protectionRect.isEmpty) { val rimPath = Path(protectionPath) @@ -96,6 +99,10 @@ class FaceScanningOverlay( } } + override fun updateVisOnUpdateCutout(): Boolean { + return false // instead, we always update the visibility whenever face scanning starts/ends + } + override fun enableShowProtection(show: Boolean) { val showScanningAnimNow = keyguardUpdateMonitor.isFaceScanning && show if (showScanningAnimNow == showScanningAnim) { diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index e09c16cafe76..f99293a9d148 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -493,6 +493,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab cutoutView.onDisplayChanged(displayId); } } + + DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(mFaceScanningViewId); + if (overlay != null) { + // handle display resolution changes + overlay.onDisplayChanged(displayId); + } + if (mScreenDecorHwcLayer != null) { mScreenDecorHwcLayer.onDisplayChanged(displayId); } @@ -801,7 +808,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab }); } // Use visibility of privacy dot views & face scanning view to determine the overlay's - // visibility if the screen decoration SW layer overlay isn't persistenly showing + // visibility if the screen decoration SW layer overlay isn't persistently showing // (ie: rounded corners always showing in SW layer) overlay.getRootView().setVisibility(getWindowVisibility(overlay, shouldOptimizeVisibility)); } @@ -960,7 +967,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right); viewsMayNeedColorUpdate.add(R.id.display_cutout); } - if (mFaceScanningFactory.getHasProviders()) { + if (getOverlayView(mFaceScanningViewId) != null) { viewsMayNeedColorUpdate.add(mFaceScanningViewId); } final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()]; @@ -1115,14 +1122,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab updateOverlayProviderViews(); } - if (mFaceScanningFactory.getHasProviders()) { - FaceScanningOverlay faceScanningOverlay = - (FaceScanningOverlay) getOverlayView(mFaceScanningViewId); - if (faceScanningOverlay != null) { - faceScanningOverlay.setFaceScanningAnimColor( - Utils.getColorAttrDefaultColor(faceScanningOverlay.getContext(), - com.android.systemui.R.attr.wallpaperTextColorAccent)); - } + FaceScanningOverlay faceScanningOverlay = + (FaceScanningOverlay) getOverlayView(mFaceScanningViewId); + if (faceScanningOverlay != null) { + faceScanningOverlay.setFaceScanningAnimColor( + Utils.getColorAttrDefaultColor(faceScanningOverlay.getContext(), + com.android.systemui.R.attr.wallpaperTextColorAccent)); } } @@ -1342,11 +1347,15 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } else { newVisible = GONE; } - if (newVisible != getVisibility()) { + if (updateVisOnUpdateCutout() && newVisible != getVisibility()) { setVisibility(newVisible); } } + protected boolean updateVisOnUpdateCutout() { + return true; + } + private void updateBoundingPath() { final Path path = displayInfo.displayCutout.getCutoutPath(); if (path != null) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 41aa112d5c7b..a097c5e76149 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -492,6 +492,9 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio( mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight()); + if (scaleFactor == Float.POSITIVE_INFINITY) { + return new PointF(mFaceAuthSensorLocation.x, mFaceAuthSensorLocation.y); + } return new PointF(mFaceAuthSensorLocation.x * scaleFactor, mFaceAuthSensorLocation.y * scaleFactor); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index aeda20f16515..cd8ca0553add 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -60,6 +60,7 @@ import android.net.ConnectivityManager; import android.net.NetworkScoreManager; import android.net.wifi.WifiManager; import android.os.BatteryStats; +import android.os.PowerExemptionManager; import android.os.PowerManager; import android.os.ServiceManager; import android.os.UserManager; @@ -377,6 +378,13 @@ public class FrameworkServicesModule { /** */ @Provides + @Singleton + static PowerExemptionManager providePowerExemptionManager(Context context) { + return context.getSystemService(PowerExemptionManager.class); + } + + /** */ + @Provides @Main public SharedPreferences provideSharePreferences(Context context) { return Prefs.get(context); diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt index 22a7cd15ee31..adc0096eed37 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -51,15 +51,17 @@ class FaceScanningProviderFactory @Inject constructor( override val hasProviders: Boolean get() { - // update display info: + if (!featureFlags.isEnabled(Flags.FACE_SCANNING_ANIM) || + authController.faceAuthSensorLocation == null) { + return false + } + + // update display info display?.getDisplayInfo(displayInfo) ?: run { Log.w(TAG, "display is null, can't update displayInfo") } - val hasDisplayCutout = DisplayCutout.getFillBuiltInDisplayCutout( + return DisplayCutout.getFillBuiltInDisplayCutout( context.resources, displayInfo.uniqueId) - return hasDisplayCutout && - authController.faceAuthSensorLocation != null && - featureFlags.isEnabled(Flags.FACE_SCANNING_ANIM) } override val providers: List<DecorProvider> @@ -110,7 +112,10 @@ class FaceScanningOverlayProviderImpl( rotation: Int, displayUniqueId: String? ) { - // no need to handle rotation changes + (view.layoutParams as FrameLayout.LayoutParams).let { + updateLayoutParams(it, rotation) + view.layoutParams = it + } } override fun inflateView( @@ -124,17 +129,40 @@ class FaceScanningOverlayProviderImpl( statusBarStateController, keyguardUpdateMonitor) view.id = viewId - view.visibility = View.INVISIBLE // only show this view when face scanning is happening - var heightLayoutParam = ViewGroup.LayoutParams.MATCH_PARENT - authController.faceAuthSensorLocation?.y?.let { - heightLayoutParam = (it * 3).toInt() + FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT).let { + updateLayoutParams(it, rotation) + parent.addView(view, it) } - parent.addView(view, FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - heightLayoutParam, - Gravity.TOP or Gravity.START)) return view } + + private fun updateLayoutParams( + layoutParams: FrameLayout.LayoutParams, + @Surface.Rotation rotation: Int + ) { + layoutParams.let { lp -> + lp.width = ViewGroup.LayoutParams.MATCH_PARENT + lp.height = ViewGroup.LayoutParams.MATCH_PARENT + authController.faceAuthSensorLocation?.y?.let { faceAuthSensorHeight -> + val faceScanningHeight = (faceAuthSensorHeight * 2).toInt() + when (rotation) { + Surface.ROTATION_0, Surface.ROTATION_180 -> + lp.height = faceScanningHeight + Surface.ROTATION_90, Surface.ROTATION_270 -> + lp.width = faceScanningHeight + } + } + + lp.gravity = when (rotation) { + Surface.ROTATION_0 -> Gravity.TOP or Gravity.START + Surface.ROTATION_90 -> Gravity.LEFT or Gravity.START + Surface.ROTATION_180 -> Gravity.BOTTOM or Gravity.END + Surface.ROTATION_270 -> Gravity.RIGHT or Gravity.END + else -> -1 /* invalid rotation */ + } + } + } } fun DisplayCutout.getBoundBaseOnCurrentRotation(): List<Int> { diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java index 3dd43866e465..f9fc1f3ca184 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationListener.NotificationHandler; @@ -33,13 +32,10 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Executor; -import javax.inject.Inject; - /*** * {@link DreamOverlayNotificationCountProvider} provides the current notification count to * registered callbacks. Ongoing notifications are not included in the count. */ -@SysUISingleton public class DreamOverlayNotificationCountProvider implements CallbackController<DreamOverlayNotificationCountProvider.Callback> { private final Set<String> mNotificationKeys = new HashSet<>(); @@ -82,7 +78,6 @@ public class DreamOverlayNotificationCountProvider } }; - @Inject public DreamOverlayNotificationCountProvider( NotificationListener notificationListener, @Background Executor bgExecutor) { diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java index e878b22f61ed..250313d0aae8 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java @@ -49,6 +49,7 @@ import com.android.systemui.util.time.DateFormatUtil; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -65,7 +66,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve private final Resources mResources; private final DateFormatUtil mDateFormatUtil; private final IndividualSensorPrivacyController mSensorPrivacyController; - private final DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider; + private final Optional<DreamOverlayNotificationCountProvider> + mDreamOverlayNotificationCountProvider; private final ZenModeController mZenModeController; private final Executor mMainExecutor; @@ -125,7 +127,7 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve NextAlarmController nextAlarmController, DateFormatUtil dateFormatUtil, IndividualSensorPrivacyController sensorPrivacyController, - DreamOverlayNotificationCountProvider dreamOverlayNotificationCountProvider, + Optional<DreamOverlayNotificationCountProvider> dreamOverlayNotificationCountProvider, ZenModeController zenModeController, StatusBarWindowStateController statusBarWindowStateController) { super(view); @@ -161,7 +163,9 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mZenModeController.addCallback(mZenModeCallback); updatePriorityModeStatusIcon(); - mDreamOverlayNotificationCountProvider.addCallback(mNotificationCountCallback); + mDreamOverlayNotificationCountProvider.ifPresent( + provider -> provider.addCallback(mNotificationCountCallback)); + mTouchInsetSession.addViewToTracking(mView); } @@ -171,7 +175,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mSensorPrivacyController.removeCallback(mSensorCallback); mNextAlarmController.removeCallback(mNextAlarmCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); - mDreamOverlayNotificationCountProvider.removeCallback(mNotificationCountCallback); + mDreamOverlayNotificationCountProvider.ifPresent( + provider -> provider.removeCallback(mNotificationCountCallback)); mTouchInsetSession.clear(); mIsAttached = false; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java index cd23f149cf7d..2dd2098a78b9 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java @@ -20,9 +20,13 @@ import android.content.Context; import android.content.res.Resources; import com.android.settingslib.dream.DreamBackend; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dreams.DreamOverlayNotificationCountProvider; import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule; +import java.util.Optional; + import javax.inject.Named; import dagger.Module; @@ -50,6 +54,18 @@ public interface DreamModule { return DreamBackend.getInstance(context); } + /** + * Provides an instance of a {@link DreamOverlayNotificationCountProvider}. + */ + @SysUISingleton + @Provides + static Optional<DreamOverlayNotificationCountProvider> + providesDreamOverlayNotificationCountProvider() { + // If we decide to bring this back, we should gate it on a config that can be changed in + // an overlay. + return Optional.empty(); + } + /** */ @Provides @Named(DREAM_ONLY_ENABLED_FOR_SYSTEM_USER) diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index bbab1fbeb74a..47c678b4b8cf 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -45,9 +45,6 @@ public class Flags { /***************************************/ // 100 - notification - public static final BooleanFlag NEW_NOTIFICATION_PIPELINE_RENDERING = - new BooleanFlag(101, true); - public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING = new BooleanFlag(103, false); diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index 550f393f4ca3..ab30db297fce 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -54,6 +54,7 @@ import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -1044,7 +1045,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Override public boolean showBeforeProvisioning() { - return false; + return Build.isDebuggable() && mGlobalSettings.getInt( + Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0; } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index c686b48278a3..99b57200a397 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -169,7 +169,8 @@ class KeyguardUnlockAnimationController @Inject constructor( playingCannedAnimation: Boolean, fromWakeAndUnlock: Boolean, unlockAnimationStartDelay: Long, - unlockAnimationDuration: Long) {} + unlockAnimationDuration: Long + ) {} /** * Called when the remote unlock animation ends, in all cases, canned or swipe-to-unlock. @@ -308,8 +309,12 @@ class KeyguardUnlockAnimationController @Inject constructor( // call onKeyguardExitRemoteAnimationFinished since that will hide the keyguard // and unlock the device as well as hiding the surface. if (surfaceBehindAlpha == 0f) { + Log.d(TAG, "surfaceBehindAlphaAnimator#onAnimationEnd") keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation( false /* cancelled */) + } else { + Log.d(TAG, "skip finishSurfaceBehindRemoteAnimation" + + " surfaceBehindAlpha=$surfaceBehindAlpha") } } }) @@ -325,6 +330,7 @@ class KeyguardUnlockAnimationController @Inject constructor( } addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { + Log.d(TAG, "surfaceBehindEntryAnimator#onAnimationEnd") playingCannedUnlockAnimation = false keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( false /* cancelled */ @@ -372,8 +378,8 @@ class KeyguardUnlockAnimationController @Inject constructor( * changed. */ override fun onKeyguardGoingAwayChanged() { - if (keyguardStateController.isKeyguardGoingAway - && !statusBarStateController.leaveOpenOnKeyguardHide()) { + if (keyguardStateController.isKeyguardGoingAway && + !statusBarStateController.leaveOpenOnKeyguardHide()) { prepareForInWindowLauncherAnimations() } } @@ -427,7 +433,7 @@ class KeyguardUnlockAnimationController @Inject constructor( launcherUnlockController?.prepareForUnlock( willUnlockWithSmartspaceTransition, /* willAnimateSmartspace */ lockscreenSmartspaceBounds, /* lockscreenSmartspaceBounds */ - selectedPage, /* selectedPage */ + selectedPage /* selectedPage */ ) } catch (e: RemoteException) { Log.e(TAG, "Remote exception in prepareForInWindowUnlockAnimations.", e) @@ -502,19 +508,23 @@ class KeyguardUnlockAnimationController @Inject constructor( * by the dismiss amount via [onKeyguardDismissAmountChanged]. */ private fun playCannedUnlockAnimation() { + Log.d(TAG, "playCannedUnlockAnimation") playingCannedUnlockAnimation = true - when { // If we're set up for in-window launcher animations, ask Launcher to play its in-window // canned animation. - willUnlockWithInWindowLauncherAnimations -> unlockToLauncherWithInWindowAnimations() + willUnlockWithInWindowLauncherAnimations -> { + Log.d(TAG, "playCannedUnlockAnimation, unlockToLauncherWithInWindowAnimations") + unlockToLauncherWithInWindowAnimations() + } // If we're waking and unlocking to a non-Launcher app surface (or Launcher in-window // animations are not available), show it immediately and end the remote animation. The // circular light reveal will show the app surface, and it looks weird if it's moving // around behind that. biometricUnlockControllerLazy.get().isWakeAndUnlock -> { + Log.d(TAG, "playCannedUnlockAnimation, isWakeAndUnlock") setSurfaceBehindAppearAmount(1f) keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( false /* cancelled */) @@ -522,7 +532,10 @@ class KeyguardUnlockAnimationController @Inject constructor( // Otherwise, we're doing a normal full-window unlock. Start this animator, which will // scale/translate the window underneath the lockscreen. - else -> surfaceBehindEntryAnimator.start() + else -> { + Log.d(TAG, "playCannedUnlockAnimation, surfaceBehindEntryAnimator#start") + surfaceBehindEntryAnimator.start() + } } } @@ -774,16 +787,17 @@ class KeyguardUnlockAnimationController @Inject constructor( } private fun fadeInSurfaceBehind() { + Log.d(TAG, "fadeInSurfaceBehind") surfaceBehindAlphaAnimator.cancel() surfaceBehindAlphaAnimator.start() } private fun fadeOutSurfaceBehind() { + Log.d(TAG, "fadeOutSurfaceBehind") surfaceBehindAlphaAnimator.cancel() surfaceBehindAlphaAnimator.reverse() } - private fun shouldPerformSmartspaceTransition(): Boolean { // Feature is disabled, so we don't want to. if (!featureFlags.isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED)) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index c5f6b7831ecf..f9a1c66af41d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -486,6 +486,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, */ private IRemoteAnimationRunner mKeyguardExitAnimationRunner; + private CentralSurfaces mCentralSurfaces; + private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = new DeviceConfig.OnPropertiesChangedListener() { @Override @@ -846,6 +848,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, + mOccluded); } + @Override + public void onLaunchAnimationEnd(boolean launchIsFullScreen) { + if (launchIsFullScreen) { + mCentralSurfaces.instantCollapseNotificationPanel(); + } + } + @NonNull @Override public ViewGroup getLaunchContainer() { @@ -2421,7 +2430,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) { Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation"); - if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + " fadeoutDuration=" + fadeoutDuration); synchronized (KeyguardViewMediator.this) { @@ -2617,7 +2626,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, * @param cancelled {@code true} if the animation was cancelled before it finishes. */ public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) { + Log.d(TAG, "onKeyguardExitRemoteAnimationFinished"); if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) { + Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled + + " surfaceAnimationRunning=" + mSurfaceBehindRemoteAnimationRunning + + " surfaceAnimationRequested=" + mSurfaceBehindRemoteAnimationRequested); return; } @@ -2631,7 +2644,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, onKeyguardExitFinished(); if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) { + Log.d(TAG, "onKeyguardExitRemoteAnimationFinished" + + "#hideKeyguardViewAfterRemoteAnimation"); mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation(); + } else { + Log.d(TAG, "skip hideKeyguardViewAfterRemoteAnimation" + + " dismissFromSwipe=" + mKeyguardStateController.isDismissingFromSwipe() + + " wasShowing=" + wasShowing); } finishSurfaceBehindRemoteAnimation(cancelled); @@ -2853,6 +2872,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, @Nullable PanelExpansionStateManager panelExpansionStateManager, BiometricUnlockController biometricUnlockController, View notificationContainer, KeyguardBypassController bypassController) { + mCentralSurfaces = centralSurfaces; mKeyguardViewControllerLazy.get().registerCentralSurfaces( centralSurfaces, panelView, diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 05da4bb4d1ad..90cca15ddf21 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -52,7 +52,7 @@ public class LogModule { return factory.create("NotifLog", 1000 /* maxSize */, false /* systrace */); } - /** Provides a logging buffer for all logs related to the data layer of notifications. */ + /** Provides a logging buffer for logs related to heads up presentation of notifications. */ @Provides @SysUISingleton @NotificationHeadsUpLog @@ -60,6 +60,14 @@ public class LogModule { return factory.create("NotifHeadsUpLog", 1000); } + /** Provides a logging buffer for notification interruption calculations. */ + @Provides + @SysUISingleton + @NotificationInterruptLog + public static LogBuffer provideNotificationInterruptLogBuffer(LogBufferFactory factory) { + return factory.create("NotifInterruptLog", 100); + } + /** Provides a logging buffer for all logs for lockscreen to shade transition events. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java new file mode 100644 index 000000000000..760fbf3928b6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 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.log.dagger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.android.systemui.log.LogBuffer; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Qualifier; + +/** A {@link LogBuffer} for notification interruption logging. */ +@Qualifier +@Documented +@Retention(RUNTIME) +public @interface NotificationInterruptLog { +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index f0ce30d2dc66..f2f275323d58 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -285,6 +285,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { Log.d(TAG, "This device is already connected! : " + device.getName()); return; } + mController.setTemporaryAllowListExceptionIfNeeded(device); mCurrentActivePosition = -1; mController.connectDevice(device); device.setState(MediaDeviceState.STATE_CONNECTING); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt index 38005db28cf6..0fa326573c9c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.AudioManager import android.media.session.MediaSessionManager +import android.os.PowerExemptionManager import android.view.View import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager @@ -43,7 +44,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>, - private val audioManager: AudioManager + private val audioManager: AudioManager, + private val powerExemptionManager: PowerExemptionManager ) { var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null @@ -54,7 +56,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( val controller = MediaOutputController(context, packageName, mediaSessionManager, lbm, starter, notifCollection, - dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager) + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, + powerExemptionManager) val dialog = MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller) mediaOutputBroadcastDialog = dialog diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 42e9af846322..247ffa7c2ef9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -44,6 +44,7 @@ import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.IBinder; +import android.os.PowerExemptionManager; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -101,6 +102,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String PAGE_CONNECTED_DEVICES_KEY = "top_level_connected_devices"; + private static final long ALLOWLIST_DURATION_MS = 20000; + private static final String ALLOWLIST_REASON = "mediaoutput:remote_transfer"; + private final String mPackageName; private final Context mContext; private final MediaSessionManager mMediaSessionManager; @@ -114,6 +118,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>(); private final AudioManager mAudioManager; + private final PowerExemptionManager mPowerExemptionManager; private final NearbyMediaDevicesManager mNearbyMediaDevicesManager; private final Map<String, Integer> mNearbyDeviceInfoMap = new ConcurrentHashMap<>(); @@ -147,7 +152,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, CommonNotifCollection notifCollection, DialogLaunchAnimator dialogLaunchAnimator, Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional, - AudioManager audioManager) { + AudioManager audioManager, + PowerExemptionManager powerExemptionManager) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; @@ -155,6 +161,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mActivityStarter = starter; mNotifCollection = notifCollection; mAudioManager = audioManager; + mPowerExemptionManager = powerExemptionManager; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); @@ -776,7 +783,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, MediaOutputController controller = new MediaOutputController(mContext, mPackageName, mMediaSessionManager, mLocalBluetoothManager, mActivityStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), - mAudioManager); + mAudioManager, mPowerExemptionManager); MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true, broadcastSender, controller); mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog); @@ -822,6 +829,17 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, broadcast.setBroadcastCode(broadcastCode.getBytes(StandardCharsets.UTF_8)); } + void setTemporaryAllowListExceptionIfNeeded(MediaDevice targetDevice) { + if (mPowerExemptionManager == null || mPackageName == null) { + Log.w(TAG, "powerExemptionManager or package name is null"); + return; + } + mPowerExemptionManager.addToTemporaryAllowList(mPackageName, + PowerExemptionManager.REASON_MEDIA_NOTIFICATION_TRANSFER, + ALLOWLIST_REASON, + ALLOWLIST_DURATION_MS); + } + String getBroadcastMetadata() { LocalBluetoothLeBroadcast broadcast = mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); @@ -840,6 +858,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, || features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK)); } + boolean isBluetoothLeDevice(@NonNull MediaDevice device) { + return device.isBLEDevice(); + } + boolean isBroadcastSupported() { LocalBluetoothLeBroadcast broadcast = mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index 9248433a4a90..a6cf408e0099 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -99,7 +99,12 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public boolean isBroadcastSupported() { - return mMediaOutputController.isBroadcastSupported(); + boolean isBluetoothLeDevice = false; + if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { + isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice( + mMediaOutputController.getCurrentConnectedMediaDevice()); + } + return mMediaOutputController.isBroadcastSupported() && isBluetoothLeDevice; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index 8701d4aba720..8249a7c0779c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.AudioManager import android.media.session.MediaSessionManager +import android.os.PowerExemptionManager import android.view.View import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.UiEventLogger @@ -45,7 +46,8 @@ class MediaOutputDialogFactory @Inject constructor( private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>, - private val audioManager: AudioManager + private val audioManager: AudioManager, + private val powerExemptionManager: PowerExemptionManager ) { companion object { private const val INTERACTION_JANK_TAG = "media_output" @@ -60,8 +62,8 @@ class MediaOutputDialogFactory @Inject constructor( val controller = MediaOutputController( context, packageName, mediaSessionManager, lbm, starter, notifCollection, - dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager - ) + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, + powerExemptionManager) val dialog = MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger) mediaOutputDialog = dialog diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt index 3cc99a8ef77e..e95976f555f8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt @@ -27,4 +27,4 @@ interface ChipInfoCommon { fun getTimeoutMs(): Long } -const val DEFAULT_TIMEOUT_MILLIS = 3000L +const val DEFAULT_TIMEOUT_MILLIS = 4000L diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt index 7cc52e428218..fe1ac80e24df 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt @@ -31,6 +31,10 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT import android.widget.LinearLayout import com.android.internal.widget.CachingIconView import com.android.settingslib.Utils @@ -56,6 +60,7 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( private val windowManager: WindowManager, private val viewUtil: ViewUtil, @Main private val mainExecutor: DelayableExecutor, + private val accessibilityManager: AccessibilityManager, private val tapGestureDetector: TapGestureDetector, private val powerManager: PowerManager, @LayoutRes private val chipLayoutRes: Int @@ -110,10 +115,16 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( } // Cancel and re-set the chip timeout each time we get a new state. + val timeout = accessibilityManager.getRecommendedTimeoutMillis( + chipInfo.getTimeoutMs().toInt(), + // Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but + // include it just to be safe. + FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS + ) cancelChipViewTimeout?.run() cancelChipViewTimeout = mainExecutor.executeDelayed( { removeChip(MediaTttRemovalReason.REASON_TIMEOUT) }, - chipInfo.getTimeoutMs() + timeout.toLong() ) } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 072263fcf38c..a5d763c5327b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -26,6 +26,7 @@ import android.os.PowerManager import android.util.Log import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -52,6 +53,7 @@ class MediaTttChipControllerReceiver @Inject constructor( windowManager: WindowManager, viewUtil: ViewUtil, mainExecutor: DelayableExecutor, + accessibilityManager: AccessibilityManager, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, @Main private val mainHandler: Handler, @@ -62,6 +64,7 @@ class MediaTttChipControllerReceiver @Inject constructor( windowManager, viewUtil, mainExecutor, + accessibilityManager, tapGestureDetector, powerManager, R.layout.media_ttt_chip_receiver diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt index 54b4380e2443..943604cff887 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt @@ -24,6 +24,7 @@ import android.util.Log import android.view.View import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager import android.widget.TextView import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R @@ -53,6 +54,7 @@ class MediaTttChipControllerSender @Inject constructor( windowManager: WindowManager, viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, + accessibilityManager: AccessibilityManager, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, private val uiEventLogger: MediaTttSenderUiEventLogger @@ -62,6 +64,7 @@ class MediaTttChipControllerSender @Inject constructor( windowManager, viewUtil, mainExecutor, + accessibilityManager, tapGestureDetector, powerManager, R.layout.media_ttt_chip diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt index f1dd5ffd2077..8179d1763ea1 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt @@ -291,7 +291,8 @@ class BackPanelController private constructor( override fun onMotionEvent(event: MotionEvent) { backAnimation?.onBackMotion( - event, + event.x, + event.y, event.actionMasked, if (mView.isLeftPanel) BackEvent.EDGE_LEFT else BackEvent.EDGE_RIGHT ) diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index e210d685a370..3039d9d56c80 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -84,13 +84,16 @@ import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto; import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.android.wm.shell.back.BackAnimation; +import com.android.wm.shell.pip.Pip; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Executor; +import java.util.function.Consumer; import javax.inject.Inject; @@ -147,16 +150,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mPackageName = "_UNKNOWN"; } } - - @Override - public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { - mIsInPipMode = true; - } - - @Override - public void onActivityUnpinned() { - mIsInPipMode = false; - } }; private DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = @@ -188,6 +181,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private final ViewConfiguration mViewConfiguration; private final WindowManager mWindowManager; private final IWindowManager mWindowManagerService; + private final Optional<Pip> mPipOptional; private final FalsingManager mFalsingManager; // Activities which should not trigger Back gesture. private final List<ComponentName> mGestureBlockingActivities = new ArrayList<>(); @@ -218,6 +212,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker // We temporarily disable back gesture when user is quickswitching // between apps of different orientations private boolean mDisabledForQuickstep; + // This gets updated when the value of PipTransitionState#isInPip changes. + private boolean mIsInPip; private final PointF mDownPoint = new PointF(); private final PointF mEndPoint = new PointF(); @@ -233,7 +229,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private boolean mIsNavBarShownTransiently; private boolean mIsBackGestureAllowed; private boolean mGestureBlockingActivityRunning; - private boolean mIsInPipMode; private boolean mIsNewBackAffordanceEnabled; private InputMonitor mInputMonitor; @@ -302,6 +297,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker } }; + private final Consumer<Boolean> mOnIsInPipStateChangedListener = + (isInPip) -> mIsInPip = isInPip; EdgeBackGestureHandler( Context context, @@ -316,6 +313,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker ViewConfiguration viewConfiguration, WindowManager windowManager, IWindowManager windowManagerService, + Optional<Pip> pipOptional, FalsingManager falsingManager, LatencyTracker latencyTracker, FeatureFlags featureFlags) { @@ -332,6 +330,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mViewConfiguration = viewConfiguration; mWindowManager = windowManager; mWindowManagerService = windowManagerService; + mPipOptional = pipOptional; mFalsingManager = falsingManager; mLatencyTracker = latencyTracker; mFeatureFlags = featureFlags; @@ -491,6 +490,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mPluginManager.removePluginListener(this); TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener); + mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null)); try { mWindowManagerService.unregisterSystemGestureExclusionListener( @@ -508,6 +508,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor::execute, mOnPropertiesChangedListener); + mPipOptional.ifPresent( + pip -> pip.setOnIsInPipStateChangedListener(mOnIsInPipStateChangedListener)); try { mWindowManagerService.registerSystemGestureExclusionListener( @@ -680,7 +682,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private boolean isWithinTouchRegion(int x, int y) { // If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back // gesture - final boolean isInsidePip = mIsInPipMode && mPipExcludedBounds.contains(x, y); + final boolean isInsidePip = mIsInPip && mPipExcludedBounds.contains(x, y); if (isInsidePip || mNavBarOverlayExcludedBounds.contains(x, y)) { return false; } @@ -933,7 +935,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker pw.println(" mInRejectedExclusion=" + mInRejectedExclusion); pw.println(" mExcludeRegion=" + mExcludeRegion); pw.println(" mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion); - pw.println(" mIsInPipMode=" + mIsInPipMode); + pw.println(" mIsInPip=" + mIsInPip); pw.println(" mPipExcludedBounds=" + mPipExcludedBounds); pw.println(" mNavBarOverlayExcludedBounds=" + mNavBarOverlayExcludedBounds); pw.println(" mEdgeWidthLeft=" + mEdgeWidthLeft); @@ -1002,6 +1004,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private final ViewConfiguration mViewConfiguration; private final WindowManager mWindowManager; private final IWindowManager mWindowManagerService; + private final Optional<Pip> mPipOptional; private final FalsingManager mFalsingManager; private final LatencyTracker mLatencyTracker; private final FeatureFlags mFeatureFlags; @@ -1018,6 +1021,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker ViewConfiguration viewConfiguration, WindowManager windowManager, IWindowManager windowManagerService, + Optional<Pip> pipOptional, FalsingManager falsingManager, LatencyTracker latencyTracker, FeatureFlags featureFlags) { @@ -1032,6 +1036,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mViewConfiguration = viewConfiguration; mWindowManager = windowManager; mWindowManagerService = windowManagerService; + mPipOptional = pipOptional; mFalsingManager = falsingManager; mLatencyTracker = latencyTracker; mFeatureFlags = featureFlags; @@ -1052,6 +1057,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mViewConfiguration, mWindowManager, mWindowManagerService, + mPipOptional, mFalsingManager, mLatencyTracker, mFeatureFlags); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java index a74c59618c95..eba9d3fdcab8 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java @@ -486,7 +486,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl public void onMotionEvent(MotionEvent event) { if (mBackAnimation != null) { mBackAnimation.onBackMotion( - event, + event.getX(), event.getY(), event.getActionMasked(), mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt index 3417d4977fa4..05038b7b1b1d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt @@ -22,6 +22,8 @@ import android.graphics.drawable.Drawable import android.graphics.drawable.RippleDrawable import android.os.UserManager import android.util.AttributeSet +import android.util.Log +import android.view.MotionEvent import android.view.View import android.widget.ImageView import android.widget.LinearLayout @@ -101,4 +103,18 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( } multiUserAvatar.setImageDrawable(pictureToSet) } -}
\ No newline at end of file + + override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { + if (VERBOSE) Log.d(TAG, "FooterActionsView onInterceptTouchEvent ${ev?.string}") + return super.onInterceptTouchEvent(ev) + } + + override fun onTouchEvent(event: MotionEvent?): Boolean { + if (VERBOSE) Log.d(TAG, "FooterActionsView onTouchEvent ${event?.string}") + return super.onTouchEvent(event) + } +} +private const val TAG = "FooterActionsView" +private val VERBOSE = Log.isLoggable(TAG, Log.VERBOSE) +private val MotionEvent.string + get() = "($id): ($x,$y)"
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java index 6cfbb43fa25a..07455a02b2cf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java @@ -66,7 +66,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim * @param entry entry to show */ public void showNotification(@NonNull NotificationEntry entry) { - mLogger.logShowNotification(entry.getKey()); + mLogger.logShowNotification(entry); addAlertEntry(entry); updateNotification(entry.getKey(), true /* alert */); entry.setInterruption(); @@ -320,7 +320,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim * @param updatePostTime whether or not to refresh the post time */ public void updateEntry(boolean updatePostTime) { - mLogger.logUpdateEntry(mEntry.getKey(), updatePostTime); + mLogger.logUpdateEntry(mEntry, updatePostTime); long currentTime = mClock.currentTimeMillis(); mEarliestRemovaltime = currentTime + mMinimumDisplayTime; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index c1ea6bf7cec8..9d80d5fbc2ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -178,7 +178,7 @@ class LockscreenShadeTransitionController @Inject constructor( val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context) private val splitShadeOverScroller: SplitShadeLockScreenOverScroller by lazy { - splitShadeOverScrollerFactory.create(qS, nsslController) + splitShadeOverScrollerFactory.create({ qS }, { nsslController }) } private val phoneShadeOverScroller: SingleShadeLockScreenOverScroller by lazy { @@ -911,4 +911,4 @@ class DragDownHelper( host.getLocationOnScreen(temp2) return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1]) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt index 96ce6b45dc71..13d8adb079de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt @@ -9,6 +9,7 @@ import android.view.animation.PathInterpolator import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R import com.android.systemui.animation.Interpolators +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.ScrimController @@ -16,16 +17,18 @@ import com.android.systemui.statusbar.policy.ConfigurationController import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import java.io.PrintWriter class SplitShadeLockScreenOverScroller @AssistedInject constructor( configurationController: ConfigurationController, + dumpManager: DumpManager, private val context: Context, private val scrimController: ScrimController, private val statusBarStateController: SysuiStatusBarStateController, - @Assisted private val qS: QS, - @Assisted private val nsslController: NotificationStackScrollLayoutController + @Assisted private val qSProvider: () -> QS, + @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController ) : LockScreenShadeOverScroller { private var releaseOverScrollAnimator: Animator? = null @@ -34,6 +37,12 @@ constructor( private var maxOverScrollAmount = 0 private var previousOverscrollAmount = 0 + private val qS: QS + get() = qSProvider() + + private val nsslController: NotificationStackScrollLayoutController + get() = nsslControllerProvider() + init { updateResources() configurationController.addCallback( @@ -42,6 +51,9 @@ constructor( updateResources() } }) + dumpManager.registerDumpable("SplitShadeLockscreenOverScroller") { printWriter, _ -> + dump(printWriter) + } } private fun updateResources() { @@ -114,11 +126,25 @@ constructor( releaseOverScrollAnimator = null } + private fun dump(printWriter: PrintWriter) { + printWriter.println( + """ + SplitShadeLockScreenOverScroller: + Resources: + transitionToFullShadeDistance: $transitionToFullShadeDistance + maxOverScrollAmount: $maxOverScrollAmount + releaseOverScrollDuration: $releaseOverScrollDuration + State: + previousOverscrollAmount: $previousOverscrollAmount + expansionDragDownAmount: $expansionDragDownAmount + """.trimIndent()) + } + @AssistedFactory fun interface Factory { fun create( - qS: QS, - nsslController: NotificationStackScrollLayoutController + qSProvider: () -> QS, + nsslControllerProvider: () -> NotificationStackScrollLayoutController ): SplitShadeLockScreenOverScroller } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java index a0ccd5726c75..1be4c04ef804 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java @@ -80,7 +80,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac @VisibleForTesting boolean isDynamicPrivacyEnabled() { - return !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic( + return mLockscreenUserManager.userAllowsNotificationsInPublic( mLockscreenUserManager.getCurrentUserId()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt index f6a55e6b75c6..478f7aa8ce09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt @@ -48,8 +48,7 @@ class NotifPipelineFlags @Inject constructor( fun assertLegacyPipelineEnabled(): Unit = check(!isNewPipelineEnabled()) { "Old pipeline code running w/ new pipeline enabled" } - fun isNewPipelineEnabled(): Boolean = - featureFlags.isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING) + fun isNewPipelineEnabled(): Boolean = true fun isDevLoggingEnabled(): Boolean = featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS new file mode 100644 index 000000000000..63c37e9584d6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS @@ -0,0 +1,12 @@ +set noparent + +# Bug component: 78010 + +aaliomer@google.com +aroederer@google.com +jeffdq@google.com +juliacr@google.com +juliatuttle@google.com +lynhan@google.com +steell@google.com +yurilin@google.com
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java index e98ae8db4122..f6a572ec6ce6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection; +import static com.android.systemui.statusbar.notification.NotificationUtils.logKey; import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED; import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED; @@ -52,7 +53,7 @@ public class ListDumper { sb, true, includeRecordKeeping, - interactionTracker.hasUserInteractedWith(entry.getKey())); + interactionTracker.hasUserInteractedWith(logKey(entry))); if (entry instanceof GroupEntry) { GroupEntry ge = (GroupEntry) entry; NotificationEntry summary = ge.getSummary(); @@ -63,7 +64,7 @@ public class ListDumper { sb, true, includeRecordKeeping, - interactionTracker.hasUserInteractedWith(summary.getKey())); + interactionTracker.hasUserInteractedWith(logKey(summary))); } List<NotificationEntry> children = ge.getChildren(); for (int childIndex = 0; childIndex < children.size(); childIndex++) { @@ -74,7 +75,7 @@ public class ListDumper { sb, true, includeRecordKeeping, - interactionTracker.hasUserInteractedWith(child.getKey())); + interactionTracker.hasUserInteractedWith(logKey(child))); } } } @@ -115,11 +116,12 @@ public class ListDumper { ) { sb.append(indent) .append("[").append(index).append("] ") - .append(entry.getKey()); + .append(index.length() == 1 ? " " : "") + .append(logKey(entry)); if (includeParent) { sb.append(" (parent=") - .append(entry.getParent() != null ? entry.getParent().getKey() : null) + .append(logKey(entry.getParent())) .append(")"); NotificationEntry notifEntry = entry.getRepresentativeEntry(); @@ -184,15 +186,15 @@ public class ListDumper { if (notifEntry.getAttachState().getSuppressedChanges().getParent() != null) { rksb.append("suppressedParent=") - .append(notifEntry.getAttachState().getSuppressedChanges() - .getParent().getKey()) + .append(logKey(notifEntry.getAttachState().getSuppressedChanges() + .getParent())) .append(" "); } if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) { rksb.append("suppressedSection=") .append(notifEntry.getAttachState().getSuppressedChanges() - .getSection()) + .getSection().getLabel()) .append(" "); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 410593ac5493..add177ddd76c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -104,6 +104,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -266,13 +267,14 @@ public class NotifCollection implements Dumpable { requireNonNull(stats); NotificationEntry storedEntry = mNotificationSet.get(entry.getKey()); if (storedEntry == null) { - mLogger.logNonExistentNotifDismissed(entry.getKey()); + mLogger.logNonExistentNotifDismissed(entry); continue; } if (entry != storedEntry) { throw mEulogizer.record( new IllegalStateException("Invalid entry: " - + "different stored and dismissed entries for " + entry.getKey())); + + "different stored and dismissed entries for " + logKey(entry) + + " stored=@" + Integer.toHexString(storedEntry.hashCode()))); } if (entry.getDismissState() == DISMISSED) { @@ -281,7 +283,7 @@ public class NotifCollection implements Dumpable { updateDismissInterceptors(entry); if (isDismissIntercepted(entry)) { - mLogger.logNotifDismissedIntercepted(entry.getKey()); + mLogger.logNotifDismissedIntercepted(entry); continue; } @@ -298,7 +300,7 @@ public class NotifCollection implements Dumpable { stats.notificationVisibility); } catch (RemoteException e) { // system process is dead if we're here. - mLogger.logRemoteExceptionOnNotificationClear(entry.getKey(), e); + mLogger.logRemoteExceptionOnNotificationClear(entry, e); } } } @@ -341,7 +343,7 @@ public class NotifCollection implements Dumpable { // interceptors the chance to filter the notification updateDismissInterceptors(entry); if (isDismissIntercepted(entry)) { - mLogger.logNotifClearAllDismissalIntercepted(entry.getKey()); + mLogger.logNotifClearAllDismissalIntercepted(entry); } entries.remove(i); } @@ -362,7 +364,7 @@ public class NotifCollection implements Dumpable { NotificationEntry entry = entries.get(i); entry.setDismissState(DISMISSED); - mLogger.logNotifDismissed(entry.getKey()); + mLogger.logNotifDismissed(entry); if (isCanceled(entry)) { canceledEntries.add(entry); @@ -415,12 +417,12 @@ public class NotifCollection implements Dumpable { int reason) { Assert.isMainThread(); - mLogger.logNotifRemoved(sbn.getKey(), reason); + mLogger.logNotifRemoved(sbn, reason); final NotificationEntry entry = mNotificationSet.get(sbn.getKey()); if (entry == null) { // TODO (b/160008901): Throw an exception here - mLogger.logNoNotificationToRemoveWithKey(sbn.getKey(), reason); + mLogger.logNoNotificationToRemoveWithKey(sbn, reason); return; } @@ -463,7 +465,7 @@ public class NotifCollection implements Dumpable { mEventQueue.add(new BindEntryEvent(entry, sbn)); mNotificationSet.put(sbn.getKey(), entry); - mLogger.logNotifPosted(sbn.getKey()); + mLogger.logNotifPosted(entry); mEventQueue.add(new EntryAddedEvent(entry)); } else { @@ -482,7 +484,7 @@ public class NotifCollection implements Dumpable { entry.setSbn(sbn); mEventQueue.add(new BindEntryEvent(entry, sbn)); - mLogger.logNotifUpdated(sbn.getKey()); + mLogger.logNotifUpdated(entry); mEventQueue.add(new EntryUpdatedEvent(entry, true /* fromSystem */)); } } @@ -497,12 +499,12 @@ public class NotifCollection implements Dumpable { if (mNotificationSet.get(entry.getKey()) != entry) { throw mEulogizer.record( new IllegalStateException("No notification to remove with key " - + entry.getKey())); + + logKey(entry))); } if (!isCanceled(entry)) { throw mEulogizer.record( - new IllegalStateException("Cannot remove notification " + entry.getKey() + new IllegalStateException("Cannot remove notification " + logKey(entry) + ": has not been marked for removal")); } @@ -513,7 +515,7 @@ public class NotifCollection implements Dumpable { } if (!isLifetimeExtended(entry)) { - mLogger.logNotifReleased(entry.getKey()); + mLogger.logNotifReleased(entry); mNotificationSet.remove(entry.getKey()); cancelDismissInterception(entry); mEventQueue.add(new EntryRemovedEvent(entry, entry.mCancellationReason)); @@ -579,7 +581,7 @@ public class NotifCollection implements Dumpable { } } } else { - mLogger.logRankingMissing(entry.getKey(), rankingMap); + mLogger.logRankingMissing(entry, rankingMap); } } } @@ -626,10 +628,7 @@ public class NotifCollection implements Dumpable { extender.getName(), logKey, collectionEntryIs))); } - mLogger.logLifetimeExtensionEnded( - entry.getKey(), - extender, - entry.mLifetimeExtenders.size()); + mLogger.logLifetimeExtensionEnded(entry, extender, entry.mLifetimeExtenders.size()); if (!isLifetimeExtended(entry)) { if (tryRemoveNotification(entry)) { @@ -656,7 +655,7 @@ public class NotifCollection implements Dumpable { mAmDispatchingToOtherCode = true; for (NotifLifetimeExtender extender : mLifetimeExtenders) { if (extender.maybeExtendLifetime(entry, entry.mCancellationReason)) { - mLogger.logLifetimeExtended(entry.getKey(), extender); + mLogger.logLifetimeExtended(entry, extender); entry.mLifetimeExtenders.add(extender); } } @@ -829,11 +828,9 @@ public class NotifCollection implements Dumpable { @Override public void dump(PrintWriter pw, @NonNull String[] args) { final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs()); + entries.sort(Comparator.comparing(NotificationEntry::getKey)); - pw.println("\t" + TAG + " unsorted/unfiltered notifications:"); - if (entries.size() == 0) { - pw.println("\t\t None"); - } + pw.println("\t" + TAG + " unsorted/unfiltered notifications: " + entries.size()); pw.println( ListDumper.dumpList( entries, @@ -917,17 +914,17 @@ public class NotifCollection implements Dumpable { // Make sure we have the notification to update NotificationEntry entry = mNotificationSet.get(sbn.getKey()); if (entry == null) { - mLogger.logNotifInternalUpdateFailed(sbn.getKey(), name, reason); + mLogger.logNotifInternalUpdateFailed(sbn, name, reason); return; } - mLogger.logNotifInternalUpdate(sbn.getKey(), name, reason); + mLogger.logNotifInternalUpdate(entry, name, reason); // First do the pieces of postNotification which are not about assuming the notification // was sent by the app entry.setSbn(sbn); mEventQueue.add(new BindEntryEvent(entry, sbn)); - mLogger.logNotifUpdated(sbn.getKey()); + mLogger.logNotifUpdated(entry); mEventQueue.add(new EntryUpdatedEvent(entry, false /* fromSystem */)); // Skip the applyRanking step and go straight to dispatching the events diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index df2fe4e8511f..702c6daac7ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -579,11 +579,7 @@ public class ShadeListBuilder implements Dumpable { if (existingSummary == null) { group.setSummary(entry); } else { - mLogger.logDuplicateSummary( - mIterationCount, - group.getKey(), - existingSummary.getKey(), - entry.getKey()); + mLogger.logDuplicateSummary(mIterationCount, group, existingSummary, entry); // Use whichever one was posted most recently if (entry.getSbn().getPostTime() @@ -1070,7 +1066,7 @@ public class ShadeListBuilder implements Dumpable { if (!Objects.equals(curr, prev)) { mLogger.logEntryAttachStateChanged( mIterationCount, - entry.getKey(), + entry, prev.getParent(), curr.getParent()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java index 8f37bafa45e6..023c4ef2b8b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java @@ -360,13 +360,13 @@ public class PreparationCoordinator implements Coordinator { } private void abortInflation(NotificationEntry entry, String reason) { - mLogger.logInflationAborted(entry.getKey(), reason); + mLogger.logInflationAborted(entry, reason); mNotifInflater.abortInflation(entry); mInflatingNotifs.remove(entry); } private void onInflationFinished(NotificationEntry entry, NotifViewController controller) { - mLogger.logNotifInflated(entry.getKey()); + mLogger.logNotifInflated(entry); mInflatingNotifs.remove(entry); mViewBarn.registerViewForEntry(entry, controller); mInflationStates.put(entry, STATE_INFLATED); @@ -398,20 +398,20 @@ public class PreparationCoordinator implements Coordinator { return false; } if (isBeyondGroupInitializationWindow(group, now)) { - mLogger.logGroupInflationTookTooLong(group.getKey()); + mLogger.logGroupInflationTookTooLong(group); return false; } if (mInflatingNotifs.contains(group.getSummary())) { - mLogger.logDelayingGroupRelease(group.getKey(), group.getSummary().getKey()); + mLogger.logDelayingGroupRelease(group, group.getSummary()); return true; } for (NotificationEntry child : group.getChildren()) { if (mInflatingNotifs.contains(child) && !child.wasAttachedInPreviousPass()) { - mLogger.logDelayingGroupRelease(group.getKey(), child.getKey()); + mLogger.logDelayingGroupRelease(group, child); return true; } } - mLogger.logDoneWaitingForGroupInflation(group.getKey()); + mLogger.logDoneWaitingForGroupInflation(group); return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt index f8352500923e..30f13152126c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt @@ -19,48 +19,51 @@ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel import com.android.systemui.log.dagger.NotificationLog +import com.android.systemui.statusbar.notification.collection.GroupEntry +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class PreparationCoordinatorLogger @Inject constructor( @NotificationLog private val buffer: LogBuffer ) { - fun logNotifInflated(key: String) { + fun logNotifInflated(entry: NotificationEntry) { buffer.log(TAG, LogLevel.DEBUG, { - str1 = key + str1 = entry.logKey }, { "NOTIF INFLATED $str1" }) } - fun logInflationAborted(key: String, reason: String) { + fun logInflationAborted(entry: NotificationEntry, reason: String) { buffer.log(TAG, LogLevel.DEBUG, { - str1 = key + str1 = entry.logKey str2 = reason }, { "NOTIF INFLATION ABORTED $str1 reason=$str2" }) } - fun logDoneWaitingForGroupInflation(groupKey: String) { + fun logDoneWaitingForGroupInflation(group: GroupEntry) { buffer.log(TAG, LogLevel.DEBUG, { - str1 = groupKey + str1 = group.logKey }, { "Finished inflating all members of group $str1, releasing group" }) } - fun logGroupInflationTookTooLong(groupKey: String) { + fun logGroupInflationTookTooLong(group: GroupEntry) { buffer.log(TAG, LogLevel.WARNING, { - str1 = groupKey + str1 = group.logKey }, { "Group inflation took too long for $str1, releasing children early" }) } - fun logDelayingGroupRelease(groupKey: String, childKey: String) { + fun logDelayingGroupRelease(group: GroupEntry, child: NotificationEntry) { buffer.log(TAG, LogLevel.DEBUG, { - str1 = groupKey - str2 = childKey + str1 = group.logKey + str2 = child.logKey }, { "Delaying release of group $str1 because child $str2 is still inflating" }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt index f8bf85f92eae..8d1759b8f475 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt @@ -23,8 +23,10 @@ import com.android.systemui.log.LogLevel.WARNING import com.android.systemui.log.dagger.NotificationLog import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry +import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class ShadeListBuilderLogger @Inject constructor( @@ -110,12 +112,17 @@ class ShadeListBuilderLogger @Inject constructor( }) } - fun logDuplicateSummary(buildId: Int, groupKey: String, existingKey: String, newKey: String) { + fun logDuplicateSummary( + buildId: Int, + group: GroupEntry, + existingSummary: NotificationEntry, + newSummary: NotificationEntry + ) { buffer.log(TAG, WARNING, { long1 = buildId.toLong() - str1 = groupKey - str2 = existingKey - str3 = newKey + str1 = group.logKey + str2 = existingSummary.logKey + str3 = newSummary.logKey }, { """(Build $long1) Duplicate summary for group "$str1": "$str2" vs. "$str3"""" }) @@ -124,7 +131,7 @@ class ShadeListBuilderLogger @Inject constructor( fun logDuplicateTopLevelKey(buildId: Int, topLevelKey: String) { buffer.log(TAG, WARNING, { long1 = buildId.toLong() - str1 = topLevelKey + str1 = logKey(topLevelKey) }, { "(Build $long1) Duplicate top-level key: $str1" }) @@ -132,15 +139,15 @@ class ShadeListBuilderLogger @Inject constructor( fun logEntryAttachStateChanged( buildId: Int, - key: String, + entry: ListEntry, prevParent: GroupEntry?, newParent: GroupEntry? ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() - str1 = key - str2 = prevParent?.key - str3 = newParent?.key + str1 = entry.logKey + str2 = prevParent?.logKey + str3 = newParent?.logKey }, { val action = if (str2 == null && str3 != null) { @@ -160,8 +167,8 @@ class ShadeListBuilderLogger @Inject constructor( fun logParentChanged(buildId: Int, prevParent: GroupEntry?, newParent: GroupEntry?) { buffer.log(TAG, INFO, { long1 = buildId.toLong() - str1 = prevParent?.key - str2 = newParent?.key + str1 = prevParent?.logKey + str2 = newParent?.logKey }, { if (str1 == null && str2 != null) { "(Build $long1) Parent is {$str2}" @@ -180,8 +187,8 @@ class ShadeListBuilderLogger @Inject constructor( ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() - str1 = suppressedParent?.key - str2 = keepingParent?.key + str1 = suppressedParent?.logKey + str2 = keepingParent?.logKey }, { "(Build $long1) Change of parent to '$str1' suppressed; keeping parent '$str2'" }) @@ -193,7 +200,7 @@ class ShadeListBuilderLogger @Inject constructor( ) { buffer.log(TAG, INFO, { long1 = buildId.toLong() - str1 = keepingParent?.key + str1 = keepingParent?.logKey }, { "(Build $long1) Group pruning suppressed; keeping parent '$str1'" }) @@ -281,7 +288,7 @@ class ShadeListBuilderLogger @Inject constructor( val entry = entries[i] buffer.log(TAG, DEBUG, { int1 = i - str1 = entry.key + str1 = entry.logKey }, { "[$int1] $str1" }) @@ -289,7 +296,7 @@ class ShadeListBuilderLogger @Inject constructor( if (entry is GroupEntry) { entry.summary?.let { buffer.log(TAG, DEBUG, { - str1 = it.key + str1 = it.logKey }, { " [*] $str1 (summary)" }) @@ -298,7 +305,7 @@ class ShadeListBuilderLogger @Inject constructor( val child = entry.children[j] buffer.log(TAG, DEBUG, { int1 = j - str1 = child.key + str1 = child.logKey }, { " [$int1] $str1" }) @@ -308,7 +315,7 @@ class ShadeListBuilderLogger @Inject constructor( } fun logPipelineRunSuppressed() = - buffer.log(TAG, INFO, {}) { "Suppressing pipeline run during animation." } + buffer.log(TAG, INFO, {}) { "Suppressing pipeline run during animation." } } private const val TAG = "ShadeListBuilder"
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt index ac0b1ee6c442..46e01c33bae3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.notifcollection import android.os.RemoteException import android.service.notification.NotificationListenerService import android.service.notification.NotificationListenerService.RankingMap +import android.service.notification.StatusBarNotification import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.DEBUG import com.android.systemui.log.LogLevel.ERROR @@ -65,9 +66,9 @@ fun cancellationReasonDebugString(@CancellationReason reason: Int) = class NotifCollectionLogger @Inject constructor( @NotificationLog private val buffer: LogBuffer ) { - fun logNotifPosted(key: String) { + fun logNotifPosted(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "POSTED $str1" }) @@ -75,49 +76,49 @@ class NotifCollectionLogger @Inject constructor( fun logNotifGroupPosted(groupKey: String, batchSize: Int) { buffer.log(TAG, INFO, { - str1 = groupKey + str1 = logKey(groupKey) int1 = batchSize }, { "POSTED GROUP $str1 ($int1 events)" }) } - fun logNotifUpdated(key: String) { + fun logNotifUpdated(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "UPDATED $str1" }) } - fun logNotifRemoved(key: String, @CancellationReason reason: Int) { + fun logNotifRemoved(sbn: StatusBarNotification, @CancellationReason reason: Int) { buffer.log(TAG, INFO, { - str1 = key + str1 = sbn.logKey int1 = reason }, { "REMOVED $str1 reason=${cancellationReasonDebugString(int1)}" }) } - fun logNotifReleased(key: String) { + fun logNotifReleased(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "RELEASED $str1" }) } - fun logNotifDismissed(key: String) { + fun logNotifDismissed(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "DISMISSED $str1" }) } - fun logNonExistentNotifDismissed(key: String) { + fun logNonExistentNotifDismissed(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "DISMISSED Non Existent $str1" }) @@ -125,7 +126,7 @@ class NotifCollectionLogger @Inject constructor( fun logChildDismissed(entry: NotificationEntry) { buffer.log(TAG, DEBUG, { - str1 = entry.key + str1 = entry.logKey }, { "CHILD DISMISSED (inferred): $str1" }) @@ -141,31 +142,31 @@ class NotifCollectionLogger @Inject constructor( fun logDismissOnAlreadyCanceledEntry(entry: NotificationEntry) { buffer.log(TAG, DEBUG, { - str1 = entry.key + str1 = entry.logKey }, { "Dismiss on $str1, which was already canceled. Trying to remove..." }) } - fun logNotifDismissedIntercepted(key: String) { + fun logNotifDismissedIntercepted(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "DISMISS INTERCEPTED $str1" }) } - fun logNotifClearAllDismissalIntercepted(key: String) { + fun logNotifClearAllDismissalIntercepted(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "CLEAR ALL DISMISSAL INTERCEPTED $str1" }) } - fun logNotifInternalUpdate(key: String, name: String, reason: String) { + fun logNotifInternalUpdate(entry: NotificationEntry, name: String, reason: String) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey str2 = name str3 = reason }, { @@ -173,9 +174,9 @@ class NotifCollectionLogger @Inject constructor( }) } - fun logNotifInternalUpdateFailed(key: String, name: String, reason: String) { + fun logNotifInternalUpdateFailed(sbn: StatusBarNotification, name: String, reason: String) { buffer.log(TAG, INFO, { - str1 = key + str1 = sbn.logKey str2 = name str3 = reason }, { @@ -183,26 +184,33 @@ class NotifCollectionLogger @Inject constructor( }) } - fun logNoNotificationToRemoveWithKey(key: String, @CancellationReason reason: Int) { + fun logNoNotificationToRemoveWithKey( + sbn: StatusBarNotification, + @CancellationReason reason: Int + ) { buffer.log(TAG, ERROR, { - str1 = key + str1 = sbn.logKey int1 = reason }, { "No notification to remove with key $str1 reason=${cancellationReasonDebugString(int1)}" }) } - fun logRankingMissing(key: String, rankingMap: RankingMap) { - buffer.log(TAG, WARNING, { str1 = key }, { "Ranking update is missing ranking for $str1" }) + fun logRankingMissing(entry: NotificationEntry, rankingMap: RankingMap) { + buffer.log(TAG, WARNING, { + str1 = entry.logKey + }, { + "Ranking update is missing ranking for $str1" + }) buffer.log(TAG, DEBUG, {}, { "Ranking map contents:" }) for (entry in rankingMap.orderedKeys) { - buffer.log(TAG, DEBUG, { str1 = entry }, { " $str1" }) + buffer.log(TAG, DEBUG, { str1 = logKey(entry) }, { " $str1" }) } } - fun logRemoteExceptionOnNotificationClear(key: String, e: RemoteException) { + fun logRemoteExceptionOnNotificationClear(entry: NotificationEntry, e: RemoteException) { buffer.log(TAG, WTF, { - str1 = key + str1 = entry.logKey str2 = e.toString() }, { "RemoteException while attempting to clear $str1:\n$str2" @@ -217,9 +225,9 @@ class NotifCollectionLogger @Inject constructor( }) } - fun logLifetimeExtended(key: String, extender: NotifLifetimeExtender) { + fun logLifetimeExtended(entry: NotificationEntry, extender: NotifLifetimeExtender) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey str2 = extender.name }, { "LIFETIME EXTENDED: $str1 by $str2" @@ -227,12 +235,12 @@ class NotifCollectionLogger @Inject constructor( } fun logLifetimeExtensionEnded( - key: String, + entry: NotificationEntry, extender: NotifLifetimeExtender, totalExtenders: Int ) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey str2 = extender.name int1 = totalExtenders }, { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java index 19cf9dc135b1..5ef2b9e55d9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinder.java @@ -83,7 +83,7 @@ public class HeadsUpViewBinder { params.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp); params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP); CancellationSignal signal = mStage.requestRebind(entry, en -> { - mLogger.entryBoundSuccessfully(entry.getKey()); + mLogger.entryBoundSuccessfully(entry); en.getRow().setUsesIncreasedHeadsUpHeight(params.useIncreasedHeadsUpHeight()); // requestRebing promises that if we called cancel before this callback would be // invoked, then we will not enter this callback, and because we always cancel before @@ -94,7 +94,7 @@ public class HeadsUpViewBinder { } }); abortBindCallback(entry); - mLogger.startBindingHun(entry.getKey()); + mLogger.startBindingHun(entry); mOngoingBindCallbacks.put(entry, signal); } @@ -105,7 +105,7 @@ public class HeadsUpViewBinder { public void abortBindCallback(NotificationEntry entry) { CancellationSignal ongoingBindCallback = mOngoingBindCallbacks.remove(entry); if (ongoingBindCallback != null) { - mLogger.currentOngoingBindingAborted(entry.getKey()); + mLogger.currentOngoingBindingAborted(entry); ongoingBindCallback.cancel(); } } @@ -116,7 +116,7 @@ public class HeadsUpViewBinder { public void unbindHeadsUpView(NotificationEntry entry) { abortBindCallback(entry); mStage.getStageParams(entry).markContentViewsFreeable(FLAG_CONTENT_VIEW_HEADS_UP); - mLogger.entryContentViewMarkedFreeable(entry.getKey()); - mStage.requestRebind(entry, e -> mLogger.entryUnbound(e.getKey())); + mLogger.entryContentViewMarkedFreeable(entry); + mStage.requestRebind(entry, e -> mLogger.entryUnbound(e)); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt index 50a6207efe0b..d1feaa05c653 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt @@ -3,44 +3,46 @@ package com.android.systemui.statusbar.notification.interruption import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.dagger.NotificationHeadsUpLog +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class HeadsUpViewBinderLogger @Inject constructor(@NotificationHeadsUpLog val buffer: LogBuffer) { - fun startBindingHun(key: String) { + fun startBindingHun(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "start binding heads up entry $str1 " }) } - fun currentOngoingBindingAborted(key: String) { + fun currentOngoingBindingAborted(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "aborted potential ongoing heads up entry binding $str1 " }) } - fun entryBoundSuccessfully(key: String) { + fun entryBoundSuccessfully(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "heads up entry bound successfully $str1 " }) } - fun entryUnbound(key: String) { + fun entryUnbound(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "heads up entry unbound successfully $str1 " }) } - fun entryContentViewMarkedFreeable(key: String) { + fun entryContentViewMarkedFreeable(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "start unbinding heads up entry $str1 " }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt index 6c99e3adb73e..016b388ff60a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt @@ -16,20 +16,19 @@ package com.android.systemui.statusbar.notification.interruption -import android.service.notification.StatusBarNotification import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.DEBUG import com.android.systemui.log.LogLevel.INFO -import com.android.systemui.log.dagger.NotificationHeadsUpLog -import com.android.systemui.log.dagger.NotificationLog +import com.android.systemui.log.dagger.NotificationInterruptLog +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class NotificationInterruptLogger @Inject constructor( - @NotificationLog val notifBuffer: LogBuffer, - @NotificationHeadsUpLog val hunBuffer: LogBuffer + @NotificationInterruptLog val buffer: LogBuffer ) { fun logHeadsUpFeatureChanged(useHeadsUp: Boolean) { - hunBuffer.log(TAG, INFO, { + buffer.log(TAG, INFO, { bool1 = useHeadsUp }, { "heads up is enabled=$bool1" @@ -37,118 +36,118 @@ class NotificationInterruptLogger @Inject constructor( } fun logWillDismissAll() { - hunBuffer.log(TAG, INFO, { + buffer.log(TAG, INFO, { }, { "dismissing any existing heads up notification on disable event" }) } - fun logNoBubbleNotAllowed(sbn: StatusBarNotification) { - notifBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoBubbleNotAllowed(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No bubble up: not allowed to bubble: $str1" }) } - fun logNoBubbleNoMetadata(sbn: StatusBarNotification) { - notifBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoBubbleNoMetadata(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No bubble up: notification: $str1 doesn't have valid metadata" }) } fun logNoHeadsUpFeatureDisabled() { - hunBuffer.log(TAG, DEBUG, { + buffer.log(TAG, DEBUG, { }, { "No heads up: no huns" }) } - fun logNoHeadsUpPackageSnoozed(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoHeadsUpPackageSnoozed(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No alerting: snoozed package: $str1" }) } - fun logNoHeadsUpAlreadyBubbled(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoHeadsUpAlreadyBubbled(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No heads up: in unlocked shade where notification is shown as a bubble: $str1" }) } - fun logNoHeadsUpSuppressedByDnd(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoHeadsUpSuppressedByDnd(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No heads up: suppressed by DND: $str1" }) } - fun logNoHeadsUpNotImportant(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoHeadsUpNotImportant(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No heads up: unimportant notification: $str1" }) } - fun logNoHeadsUpNotInUse(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoHeadsUpNotInUse(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No heads up: not in use: $str1" }) } fun logNoHeadsUpSuppressedBy( - sbn: StatusBarNotification, + entry: NotificationEntry, suppressor: NotificationInterruptSuppressor ) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + buffer.log(TAG, DEBUG, { + str1 = entry.logKey str2 = suppressor.name }, { "No heads up: aborted by suppressor: $str2 sbnKey=$str1" }) } - fun logHeadsUp(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logHeadsUp(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "Heads up: $str1" }) } - fun logNoAlertingFilteredOut(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoAlertingFilteredOut(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No alerting: filtered notification: $str1" }) } - fun logNoAlertingGroupAlertBehavior(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoAlertingGroupAlertBehavior(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No alerting: suppressed due to group alert behavior: $str1" }) } fun logNoAlertingSuppressedBy( - sbn: StatusBarNotification, + entry: NotificationEntry, suppressor: NotificationInterruptSuppressor, awake: Boolean ) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + buffer.log(TAG, DEBUG, { + str1 = entry.logKey str2 = suppressor.name bool1 = awake }, { @@ -156,65 +155,65 @@ class NotificationInterruptLogger @Inject constructor( }) } - fun logNoAlertingRecentFullscreen(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoAlertingRecentFullscreen(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No alerting: recent fullscreen: $str1" }) } - fun logNoPulsingSettingDisabled(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoPulsingSettingDisabled(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No pulsing: disabled by setting: $str1" }) } - fun logNoPulsingBatteryDisabled(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoPulsingBatteryDisabled(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No pulsing: disabled by battery saver: $str1" }) } - fun logNoPulsingNoAlert(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoPulsingNoAlert(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No pulsing: notification shouldn't alert: $str1" }) } - fun logNoPulsingNoAmbientEffect(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoPulsingNoAmbientEffect(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No pulsing: ambient effect suppressed: $str1" }) } - fun logNoPulsingNotImportant(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logNoPulsingNotImportant(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "No pulsing: not important enough: $str1" }) } - fun logPulsing(sbn: StatusBarNotification) { - hunBuffer.log(TAG, DEBUG, { - str1 = sbn.key + fun logPulsing(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "Pulsing: $str1" }) } - fun keyguardHideNotification(key: String) { - hunBuffer.log(TAG, DEBUG, { - str1 = key + fun keyguardHideNotification(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey }, { "Keyguard Hide Notification: $str1" }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index a063dbd99626..8378b69bee9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -147,14 +147,14 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter } if (!entry.canBubble()) { - mLogger.logNoBubbleNotAllowed(sbn); + mLogger.logNoBubbleNotAllowed(entry); return false; } if (entry.getBubbleMetadata() == null || (entry.getBubbleMetadata().getShortcutId() == null && entry.getBubbleMetadata().getIntent() == null)) { - mLogger.logNoBubbleNoMetadata(sbn); + mLogger.logNoBubbleNoMetadata(entry); return false; } @@ -203,23 +203,23 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter } if (isSnoozedPackage(sbn)) { - mLogger.logNoHeadsUpPackageSnoozed(sbn); + mLogger.logNoHeadsUpPackageSnoozed(entry); return false; } boolean inShade = mStatusBarStateController.getState() == SHADE; if (entry.isBubble() && inShade) { - mLogger.logNoHeadsUpAlreadyBubbled(sbn); + mLogger.logNoHeadsUpAlreadyBubbled(entry); return false; } if (entry.shouldSuppressPeek()) { - mLogger.logNoHeadsUpSuppressedByDnd(sbn); + mLogger.logNoHeadsUpSuppressedByDnd(entry); return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { - mLogger.logNoHeadsUpNotImportant(sbn); + mLogger.logNoHeadsUpNotImportant(entry); return false; } @@ -232,17 +232,17 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter boolean inUse = mPowerManager.isScreenOn() && !isDreaming; if (!inUse) { - mLogger.logNoHeadsUpNotInUse(sbn); + mLogger.logNoHeadsUpNotInUse(entry); return false; } for (int i = 0; i < mSuppressors.size(); i++) { if (mSuppressors.get(i).suppressAwakeHeadsUp(entry)) { - mLogger.logNoHeadsUpSuppressedBy(sbn, mSuppressors.get(i)); + mLogger.logNoHeadsUpSuppressedBy(entry, mSuppressors.get(i)); return false; } } - mLogger.logHeadsUp(sbn); + mLogger.logHeadsUp(entry); return true; } @@ -254,38 +254,36 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter * @return true if the entry should ambient pulse, false otherwise */ private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) { - StatusBarNotification sbn = entry.getSbn(); - if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) { - mLogger.logNoPulsingSettingDisabled(sbn); + mLogger.logNoPulsingSettingDisabled(entry); return false; } if (mBatteryController.isAodPowerSave()) { - mLogger.logNoPulsingBatteryDisabled(sbn); + mLogger.logNoPulsingBatteryDisabled(entry); return false; } if (!canAlertCommon(entry)) { - mLogger.logNoPulsingNoAlert(sbn); + mLogger.logNoPulsingNoAlert(entry); return false; } if (!canAlertHeadsUpCommon(entry)) { - mLogger.logNoPulsingNoAlert(sbn); + mLogger.logNoPulsingNoAlert(entry); return false; } if (entry.shouldSuppressAmbient()) { - mLogger.logNoPulsingNoAmbientEffect(sbn); + mLogger.logNoPulsingNoAmbientEffect(entry); return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) { - mLogger.logNoPulsingNotImportant(sbn); + mLogger.logNoPulsingNotImportant(entry); return false; } - mLogger.logPulsing(sbn); + mLogger.logPulsing(entry); return true; } @@ -296,22 +294,20 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter * @return true if these checks pass, false if the notification should not alert */ private boolean canAlertCommon(NotificationEntry entry) { - StatusBarNotification sbn = entry.getSbn(); - if (!mFlags.isNewPipelineEnabled() && mNotificationFilter.shouldFilterOut(entry)) { - mLogger.logNoAlertingFilteredOut(sbn); + mLogger.logNoAlertingFilteredOut(entry); return false; } for (int i = 0; i < mSuppressors.size(); i++) { if (mSuppressors.get(i).suppressInterruptions(entry)) { - mLogger.logNoAlertingSuppressedBy(sbn, mSuppressors.get(i), /* awake */ false); + mLogger.logNoAlertingSuppressedBy(entry, mSuppressors.get(i), /* awake */ false); return false; } } if (mKeyguardNotificationVisibilityProvider.shouldHideNotification(entry)) { - mLogger.keyguardHideNotification(entry.getKey()); + mLogger.keyguardHideNotification(entry); return false; } @@ -329,12 +325,12 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter // Don't alert notifications that are suppressed due to group alert behavior if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) { - mLogger.logNoAlertingGroupAlertBehavior(sbn); + mLogger.logNoAlertingGroupAlertBehavior(entry); return false; } if (entry.hasJustLaunchedFullScreenIntent()) { - mLogger.logNoAlertingRecentFullscreen(sbn); + mLogger.logNoAlertingRecentFullscreen(entry); return false; } @@ -352,7 +348,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter for (int i = 0; i < mSuppressors.size(); i++) { if (mSuppressors.get(i).suppressAwakeInterruptions(entry)) { - mLogger.logNoAlertingSuppressedBy(sbn, mSuppressors.get(i), /* awake */ true); + mLogger.logNoAlertingSuppressedBy(entry, mSuppressors.get(i), /* awake */ true); return false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index b785435f41f2..cd4a44e1c6e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -141,7 +141,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f; private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30); - private boolean mUpdateBackgroundOnUpdate; + private boolean mUpdateSelfBackgroundOnUpdate; private boolean mNotificationTranslationFinished = false; private boolean mIsSnoozed; private boolean mIsFaded; @@ -553,9 +553,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView updateLimits(); updateShelfIconColor(); updateRippleAllowed(); - if (mUpdateBackgroundOnUpdate) { - mUpdateBackgroundOnUpdate = false; - updateBackgroundColors(); + if (mUpdateSelfBackgroundOnUpdate) { + // Because this is triggered by UiMode change which we already propagated to children, + // we know that child rows will receive the same event, and will update their own + // backgrounds when they finish inflating, so propagating again would be redundant. + mUpdateSelfBackgroundOnUpdate = false; + updateBackgroundColorsOfSelf(); + } + } + + private void updateBackgroundColorsOfSelf() { + super.updateBackgroundColors(); + } + + @Override + public void updateBackgroundColors() { + // Because this call is made by the NSSL only on attached rows at the moment of the + // UiMode or Theme change, we have to propagate to our child views. + updateBackgroundColorsOfSelf(); + if (mIsSummaryWithChildren) { + for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) { + child.updateBackgroundColors(); + } } } @@ -1242,7 +1261,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } public void onUiModeChanged() { - mUpdateBackgroundOnUpdate = true; + mUpdateSelfBackgroundOnUpdate = true; reInflateViews(); if (mChildrenContainer != null) { for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index 599039d46556..a493a676e3d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.notification.NotificationUtils.logKey; import android.util.Log; import android.view.View; @@ -247,7 +248,7 @@ public class ExpandableNotificationRowController implements NotifViewController @Override @NonNull public String getNodeLabel() { - return mView.getEntry().getKey(); + return logKey(mView.getEntry()); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java index c66140822d92..99a24cb3e9ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java @@ -67,6 +67,7 @@ public class HybridConversationNotificationView extends HybridNotificationView { mConversationIconView = requireViewById(com.android.internal.R.id.conversation_icon); mConversationFacePile = requireViewById(com.android.internal.R.id.conversation_face_pile); mConversationSenderName = requireViewById(R.id.conversation_notification_sender); + applyTextColor(mConversationSenderName, mSecondaryTextColor); mFacePileSize = getResources() .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_size); mFacePileAvatarSize = getResources() @@ -75,6 +76,9 @@ public class HybridConversationNotificationView extends HybridNotificationView { .getDimensionPixelSize(R.dimen.conversation_single_line_avatar_size); mFacePileProtectionWidth = getResources().getDimensionPixelSize( R.dimen.conversation_single_line_face_pile_protection_width); + mTransformationHelper.setCustomTransformation( + new FadeOutAndDownWithTitleTransformation(mConversationSenderName), + mConversationSenderName.getId()); mTransformationHelper.addViewTransformingToSimilar(mConversationIconView); mTransformationHelper.addTransformedView(mConversationSenderName); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java index 40a44ffd7fe3..77fd05186090 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java @@ -24,7 +24,6 @@ import android.content.Context; import android.content.res.Resources; import android.service.notification.StatusBarNotification; import android.util.TypedValue; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -57,10 +56,8 @@ public class HybridGroupManager { mOverflowNumberPadding = res.getDimensionPixelSize(R.dimen.group_overflow_number_padding); } - private HybridNotificationView inflateHybridViewWithStyle(int style, - View contentView, ViewGroup parent) { - LayoutInflater inflater = new ContextThemeWrapper(mContext, style) - .getSystemService(LayoutInflater.class); + private HybridNotificationView inflateHybridView(View contentView, ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(mContext); int layout = contentView instanceof ConversationLayout ? R.layout.hybrid_conversation_notification : R.layout.hybrid_notification; @@ -93,16 +90,8 @@ public class HybridGroupManager { public HybridNotificationView bindFromNotification(HybridNotificationView reusableView, View contentView, StatusBarNotification notification, ViewGroup parent) { - return bindFromNotificationWithStyle(reusableView, contentView, notification, - R.style.HybridNotification, parent); - } - - private HybridNotificationView bindFromNotificationWithStyle( - HybridNotificationView reusableView, View contentView, - StatusBarNotification notification, - int style, ViewGroup parent) { if (reusableView == null) { - reusableView = inflateHybridViewWithStyle(style, contentView, parent); + reusableView = inflateHybridView(contentView, parent); } CharSequence titleText = resolveTitle(notification.getNotification()); CharSequence contentText = resolveText(notification.getNotification()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java index c0d85a6a16ef..fc9d9e8b736c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java @@ -16,13 +16,18 @@ package com.android.systemui.statusbar.notification.row; +import static android.app.Notification.COLOR_INVALID; + import android.annotation.Nullable; import android.content.Context; +import android.content.res.TypedArray; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.TextView; +import androidx.annotation.ColorInt; + import com.android.keyguard.AlphaOptimizedLinearLayout; import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; @@ -40,6 +45,8 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper(); protected TextView mTitleView; protected TextView mTextView; + protected int mPrimaryTextColor = COLOR_INVALID; + protected int mSecondaryTextColor = COLOR_INVALID; public HybridNotificationView(Context context) { this(context, null); @@ -69,42 +76,37 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout @Override protected void onFinishInflate() { super.onFinishInflate(); + resolveThemeTextColors(); mTitleView = findViewById(R.id.notification_title); mTextView = findViewById(R.id.notification_text); + applyTextColor(mTitleView, mPrimaryTextColor); + applyTextColor(mTextView, mSecondaryTextColor); mTransformationHelper.setCustomTransformation( - new ViewTransformationHelper.CustomTransformation() { - @Override - public boolean transformTo(TransformState ownState, TransformableView notification, - float transformationAmount) { - // We want to transform to the same y location as the title - TransformState otherState = notification.getCurrentState( - TRANSFORMING_VIEW_TITLE); - CrossFadeHelper.fadeOut(mTextView, transformationAmount); - if (otherState != null) { - ownState.transformViewVerticalTo(otherState, transformationAmount); - otherState.recycle(); - } - return true; - } - - @Override - public boolean transformFrom(TransformState ownState, - TransformableView notification, float transformationAmount) { - // We want to transform from the same y location as the title - TransformState otherState = notification.getCurrentState( - TRANSFORMING_VIEW_TITLE); - CrossFadeHelper.fadeIn(mTextView, transformationAmount, true /* remap */); - if (otherState != null) { - ownState.transformViewVerticalFrom(otherState, transformationAmount); - otherState.recycle(); - } - return true; - } - }, TRANSFORMING_VIEW_TEXT); + new FadeOutAndDownWithTitleTransformation(mTextView), + TRANSFORMING_VIEW_TEXT); mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, mTitleView); mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TEXT, mTextView); } + protected void applyTextColor(TextView textView, @ColorInt int textColor) { + if (textColor != COLOR_INVALID) { + textView.setTextColor(textColor); + } + } + + private void resolveThemeTextColors() { + try (TypedArray ta = mContext.getTheme().obtainStyledAttributes( + android.R.style.Theme_DeviceDefault_DayNight, new int[]{ + android.R.attr.textColorPrimary, + android.R.attr.textColorSecondary + })) { + if (ta != null) { + mPrimaryTextColor = ta.getColor(0, mPrimaryTextColor); + mSecondaryTextColor = ta.getColor(1, mSecondaryTextColor); + } + } + } + public void bind(@Nullable CharSequence title, @Nullable CharSequence text, @Nullable View contentView) { mTitleView.setText(title); @@ -152,4 +154,40 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout @Override public void setNotificationFaded(boolean faded) {} + + protected static class FadeOutAndDownWithTitleTransformation extends + ViewTransformationHelper.CustomTransformation { + + private final View mView; + + public FadeOutAndDownWithTitleTransformation(View view) { + mView = view; + } + + @Override + public boolean transformTo(TransformState ownState, TransformableView notification, + float transformationAmount) { + // We want to transform to the same y location as the title + TransformState otherState = notification.getCurrentState(TRANSFORMING_VIEW_TITLE); + CrossFadeHelper.fadeOut(mView, transformationAmount); + if (otherState != null) { + ownState.transformViewVerticalTo(otherState, transformationAmount); + otherState.recycle(); + } + return true; + } + + @Override + public boolean transformFrom(TransformState ownState, + TransformableView notification, float transformationAmount) { + // We want to transform from the same y location as the title + TransformState otherState = notification.getCurrentState(TRANSFORMING_VIEW_TITLE); + CrossFadeHelper.fadeIn(mView, transformationAmount, true /* remap */); + if (otherState != null) { + ownState.transformViewVerticalFrom(otherState, transformationAmount); + otherState.recycle(); + } + return true; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java index f693ebbb7830..ea564ddb9193 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java @@ -112,7 +112,8 @@ public final class NotifBindPipeline { public void manageRow( @NonNull NotificationEntry entry, @NonNull ExpandableNotificationRow row) { - mLogger.logManagedRow(entry.getKey()); + mLogger.logManagedRow(entry); + mLogger.logManagedRow(entry); final BindEntry bindEntry = getBindEntry(entry); if (bindEntry == null) { @@ -154,12 +155,12 @@ public final class NotifBindPipeline { * the real work once rather than repeatedly start and cancel it. */ private void requestPipelineRun(NotificationEntry entry) { - mLogger.logRequestPipelineRun(entry.getKey()); + mLogger.logRequestPipelineRun(entry); final BindEntry bindEntry = getBindEntry(entry); if (bindEntry.row == null) { // Row is not managed yet but may be soon. Stop for now. - mLogger.logRequestPipelineRowNotSet(entry.getKey()); + mLogger.logRequestPipelineRowNotSet(entry); return; } @@ -177,7 +178,7 @@ public final class NotifBindPipeline { * callbacks when the run finishes. If a run is already in progress, it is restarted. */ private void startPipeline(NotificationEntry entry) { - mLogger.logStartPipeline(entry.getKey()); + mLogger.logStartPipeline(entry); if (mStage == null) { throw new IllegalStateException("No stage was ever set on the pipeline"); @@ -193,7 +194,7 @@ public final class NotifBindPipeline { final BindEntry bindEntry = getBindEntry(entry); final Set<BindCallback> callbacks = bindEntry.callbacks; - mLogger.logFinishedPipeline(entry.getKey(), callbacks.size()); + mLogger.logFinishedPipeline(entry, callbacks.size()); bindEntry.invalidated = false; // Move all callbacks to separate list as callbacks may themselves add/remove callbacks. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt index ec406f0524ff..ab91926d466a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.row import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.dagger.NotificationLog +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class NotifBindPipelineLogger @Inject constructor( @@ -32,41 +34,41 @@ class NotifBindPipelineLogger @Inject constructor( }) } - fun logManagedRow(notifKey: String) { + fun logManagedRow(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = notifKey + str1 = entry.logKey }, { "Row set for notif: $str1" }) } - fun logRequestPipelineRun(notifKey: String) { + fun logRequestPipelineRun(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = notifKey + str1 = entry.logKey }, { "Request pipeline run for notif: $str1" }) } - fun logRequestPipelineRowNotSet(notifKey: String) { + fun logRequestPipelineRowNotSet(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = notifKey + str1 = entry.logKey }, { "Row is not set so pipeline will not run. notif = $str1" }) } - fun logStartPipeline(notifKey: String) { + fun logStartPipeline(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = notifKey + str1 = entry.logKey }, { "Start pipeline for notif: $str1" }) } - fun logFinishedPipeline(notifKey: String, numCallbacks: Int) { + fun logFinishedPipeline(entry: NotificationEntry, numCallbacks: Int) { buffer.log(TAG, INFO, { - str1 = notifKey + str1 = entry.logKey int1 = numCallbacks }, { "Finished pipeline for notif $str1 with $int1 callbacks" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java index 3616f8faee1e..81cf14646465 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java @@ -57,7 +57,7 @@ public class RowContentBindStage extends BindStage<RowContentBindParams> { @NonNull StageCallback callback) { RowContentBindParams params = getStageParams(entry); - mLogger.logStageParams(entry.getKey(), params.toString()); + mLogger.logStageParams(entry, params); // Resolve content to bind/unbind. @InflationFlag int inflationFlags = params.getContentViews(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt index 29cce3375c8a..f9923b2254d7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt @@ -19,17 +19,19 @@ package com.android.systemui.statusbar.notification.row import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.dagger.NotificationLog +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class RowContentBindStageLogger @Inject constructor( @NotificationLog private val buffer: LogBuffer ) { - fun logStageParams(notifKey: String, stageParams: String) { + fun logStageParams(entry: NotificationEntry, stageParams: RowContentBindParams) { buffer.log(TAG, INFO, { - str1 = notifKey - str2 = stageParams + str1 = entry.logKey + str2 = stageParams.toString() }, { - "Invalidated notif $str1 with params: \n$str2" + "Invalidated notif $str1 with params: $str2" }) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 213f00b8e03d..2fd02d9f1cd9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -748,19 +748,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - private void logHunSkippedForUnexpectedState(String key, boolean expected, boolean actual) { + private void logHunSkippedForUnexpectedState(ExpandableNotificationRow enr, + boolean expected, boolean actual) { if (mLogger == null) return; - mLogger.hunSkippedForUnexpectedState(key, expected, actual); + mLogger.hunSkippedForUnexpectedState(enr.getEntry(), expected, actual); } - private void logHunAnimationSkipped(String key, String reason) { + private void logHunAnimationSkipped(ExpandableNotificationRow enr, String reason) { if (mLogger == null) return; - mLogger.hunAnimationSkipped(key, reason); + mLogger.hunAnimationSkipped(enr.getEntry(), reason); } - private void logHunAnimationEventAdded(String key, int type) { + private void logHunAnimationEventAdded(ExpandableNotificationRow enr, int type) { if (mLogger == null) return; - mLogger.hunAnimationEventAdded(key, type); + mLogger.hunAnimationEventAdded(enr.getEntry(), type); } private void onDrawDebug(Canvas canvas) { @@ -3174,7 +3175,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (isHeadsUp != row.isHeadsUp()) { // For cases where we have a heads up showing and appearing again we shouldn't // do the animations at all. - logHunSkippedForUnexpectedState(key, isHeadsUp, row.isHeadsUp()); + logHunSkippedForUnexpectedState(row, isHeadsUp, row.isHeadsUp()); continue; } int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER; @@ -3192,7 +3193,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (row.isChildInGroup()) { // We can otherwise get stuck in there if it was just isolated row.setHeadsUpAnimatingAway(false); - logHunAnimationSkipped(key, "row is child in group"); + logHunAnimationSkipped(row, "row is child in group"); continue; } } else { @@ -3200,7 +3201,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (viewState == null) { // A view state was never generated for this view, so we don't need to animate // this. This may happen with notification children. - logHunAnimationSkipped(key, "row has no viewState"); + logHunAnimationSkipped(row, "row has no viewState"); continue; } if (isHeadsUp && (mAddedHeadsUpChildren.contains(row) || pinnedAndClosed)) { @@ -3224,7 +3225,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable + " onBottom=" + onBottom + " row=" + row.getEntry().getKey()); } - logHunAnimationEventAdded(key, type); + logHunAnimationEventAdded(row, type); } mHeadsUpChangeAnimations.clear(); mAddedHeadsUpChildren.clear(); @@ -4360,8 +4361,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable /** * Update colors of "dismiss" and "empty shade" views. - * - * @param lightTheme True if light theme should be used. */ @ShadeViewRefactor(RefactorComponent.DECORATOR) void updateDecorViews() { @@ -4777,8 +4776,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (SPEW) { Log.v(TAG, "generateHeadsUpAnimation: previous hun appear animation cancelled"); } - logHunAnimationSkipped(row.getEntry().getKey(), - "previous hun appear animation cancelled"); + logHunAnimationSkipped(row, "previous hun appear animation cancelled"); return; } mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt index 04bf62104f66..5f79c0e3913a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt @@ -3,21 +3,27 @@ package com.android.systemui.statusbar.notification.stack import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.dagger.NotificationHeadsUpLog -import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.* +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER import javax.inject.Inject class NotificationStackScrollLogger @Inject constructor( @NotificationHeadsUpLog private val buffer: LogBuffer ) { - fun hunAnimationSkipped(key: String, reason: String) { + fun hunAnimationSkipped(entry: NotificationEntry, reason: String) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey str2 = reason }, { "heads up animation skipped: key: $str1 reason: $str2" }) } - fun hunAnimationEventAdded(key: String, type: Int) { + fun hunAnimationEventAdded(entry: NotificationEntry, type: Int) { val reason: String reason = if (type == ANIMATION_TYPE_HEADS_UP_DISAPPEAR) { "HEADS_UP_DISAPPEAR" @@ -33,16 +39,16 @@ class NotificationStackScrollLogger @Inject constructor( type.toString() } buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey str2 = reason }, { "heads up animation added: $str1 with type $str2" }) } - fun hunSkippedForUnexpectedState(key: String, expected: Boolean, actual: Boolean) { + fun hunSkippedForUnexpectedState(entry: NotificationEntry, expected: Boolean, actual: Boolean) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey bool1 = expected bool2 = actual }, { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt index 77377af9ddfb..cb4a0884fea4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt @@ -3,6 +3,7 @@ package com.android.systemui.statusbar.notification.stack import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel import com.android.systemui.log.dagger.NotificationHeadsUpLog +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject class StackStateLogger @Inject constructor( @@ -10,7 +11,7 @@ class StackStateLogger @Inject constructor( ) { fun logHUNViewDisappearing(key: String) { buffer.log(TAG, LogLevel.INFO, { - str1 = key + str1 = logKey(key) }, { "Heads up view disappearing $str1 " }) @@ -18,7 +19,7 @@ class StackStateLogger @Inject constructor( fun logHUNViewAppearing(key: String) { buffer.log(TAG, LogLevel.INFO, { - str1 = key + str1 = logKey(key) }, { "Heads up notification view appearing $str1 " }) @@ -26,7 +27,7 @@ class StackStateLogger @Inject constructor( fun logHUNViewDisappearingWithRemoveEvent(key: String) { buffer.log(TAG, LogLevel.ERROR, { - str1 = key + str1 = logKey(key) }, { "Heads up view disappearing $str1 for ANIMATION_TYPE_REMOVE" }) @@ -34,7 +35,7 @@ class StackStateLogger @Inject constructor( fun logHUNViewAppearingWithAddEvent(key: String) { buffer.log(TAG, LogLevel.ERROR, { - str1 = key + str1 = logKey(key) }, { "Heads up view disappearing $str1 for ANIMATION_TYPE_ADD" }) @@ -42,7 +43,7 @@ class StackStateLogger @Inject constructor( fun disappearAnimationEnded(key: String) { buffer.log(TAG, LogLevel.INFO, { - str1 = key + str1 = logKey(key) }, { "Heads up notification disappear animation ended $str1 " }) @@ -50,7 +51,7 @@ class StackStateLogger @Inject constructor( fun appearAnimationEnded(key: String) { buffer.log(TAG, LogLevel.INFO, { - str1 = key + str1 = logKey(key) }, { "Heads up notification appear animation ended $str1 " }) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 8c6176408821..5181af773d9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -1597,7 +1597,7 @@ public class CentralSurfacesImpl extends CoreStartable implements } } }); - mStatusBarKeyguardViewManager.registerCentralSurfaces( + mKeyguardViewMediator.registerCentralSurfaces( /* statusBar= */ this, mNotificationPanelViewController, mPanelExpansionStateManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 33e54a77bfb3..70773005d0b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -1670,7 +1670,6 @@ public class NotificationPanelViewController extends PanelViewController { setQsExpansionEnabled(); } - @Override public void resetViews(boolean animate) { mIsLaunchTransitionFinished = false; mBlockTouches = false; @@ -4194,6 +4193,11 @@ public class NotificationPanelViewController extends PanelViewController { @Override public boolean onInterceptTouchEvent(MotionEvent event) { + if (SPEW_LOGCAT) { + Log.v(TAG, + "NPVC onInterceptTouchEvent (" + event.getId() + "): (" + event.getX() + + "," + event.getY() + ")"); + } if (mBlockTouches || mQs.disallowPanelTouches()) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS new file mode 100644 index 000000000000..18f0fb38999c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS @@ -0,0 +1,3 @@ +per-file *Notification* = set noparent +per-file *Notification* = file:../notification/OWNERS +per-file NotificationIcon* = ccassidy@google.com, evanlaird@google.com, pixel@google.com
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 9f0ecb9d4096..ed12b00cc644 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -1163,8 +1163,6 @@ public abstract class PanelViewController { mTouchDisabled ? "T" : "f")); } - public abstract void resetViews(boolean animate); - public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) { mHeadsUpManager = headsUpManager; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionController.kt index 1740bcbbefc8..16f28e7d1a21 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionController.kt @@ -2,10 +2,13 @@ package com.android.systemui.statusbar.phone.shade.transition import android.content.res.Configuration import android.content.res.Resources +import android.util.MathUtils.constrain import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.StatusBarState +import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent import com.android.systemui.statusbar.policy.ConfigurationController @@ -21,7 +24,8 @@ constructor( configurationController: ConfigurationController, dumpManager: DumpManager, private val scrimController: ScrimController, - @Main private val resources: Resources + @Main private val resources: Resources, + private val statusBarStateController: SysuiStatusBarStateController, ) { private var inSplitShade = false @@ -55,19 +59,23 @@ constructor( } private fun calculateScrimExpansionFraction(expansionEvent: PanelExpansionChangeEvent): Float { - return if (inSplitShade) { - expansionEvent.dragDownPxAmount / splitShadeScrimTransitionDistance + return if (inSplitShade && isScreenUnlocked()) { + constrain(expansionEvent.dragDownPxAmount / splitShadeScrimTransitionDistance, 0f, 1f) } else { expansionEvent.fraction } } + private fun isScreenUnlocked() = + statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE + private fun dump(printWriter: PrintWriter, args: Array<String>) { printWriter.println( """ ScrimShadeTransitionController: Resources: inSplitShade: $inSplitShade + isScreenUnlocked: ${isScreenUnlocked()} splitShadeScrimTransitionDistance: $splitShadeScrimTransitionDistance State: lastExpansionFraction: $lastExpansionFraction diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionController.kt index 4b4f1e06d980..e967d4af19b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionController.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.res.Configuration import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.NotificationPanelViewController @@ -11,6 +12,7 @@ import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager import com.android.systemui.statusbar.phone.panelstate.PanelState import com.android.systemui.statusbar.policy.ConfigurationController +import java.io.PrintWriter import javax.inject.Inject /** Controls the shade expansion transition on non-lockscreen. */ @@ -20,6 +22,7 @@ class ShadeTransitionController constructor( configurationController: ConfigurationController, panelExpansionStateManager: PanelExpansionStateManager, + dumpManager: DumpManager, private val context: Context, private val splitShadeOverScrollerFactory: SplitShadeOverScroller.Factory, private val noOpOverScroller: NoOpOverScroller, @@ -33,7 +36,7 @@ constructor( private var inSplitShade = false private val splitShadeOverScroller by lazy { - splitShadeOverScrollerFactory.create(qs, notificationStackScrollLayoutController) + splitShadeOverScrollerFactory.create({ qs }, { notificationStackScrollLayoutController }) } private val shadeOverScroller: ShadeOverScroller get() = @@ -53,6 +56,9 @@ constructor( }) panelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged) panelExpansionStateManager.addStateListener(this::onPanelStateChanged) + dumpManager.registerDumpable("ShadeTransitionController") { printWriter, _ -> + dump(printWriter) + } } private fun updateResources() { @@ -72,4 +78,15 @@ constructor( this::qs.isInitialized && this::notificationPanelViewController.isInitialized && this::notificationStackScrollLayoutController.isInitialized + + private fun dump(pw: PrintWriter) { + pw.println( + """ + ShadeTransitionController: + inSplitShade: $inSplitShade + qs.isInitialized: ${this::qs.isInitialized} + npvc.isInitialized: ${this::notificationPanelViewController.isInitialized} + nssl.isInitialized: ${this::notificationStackScrollLayoutController.isInitialized} + """.trimIndent()) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScroller.kt index d9ccc7ff2369..c25aab8eb80f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScroller.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScroller.kt @@ -28,8 +28,8 @@ constructor( dumpManager: DumpManager, private val context: Context, private val scrimController: ScrimController, - @Assisted private val qS: QS, - @Assisted private val nsslController: NotificationStackScrollLayoutController + @Assisted private val qSProvider: () -> QS, + @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController ) : ShadeOverScroller { private var releaseOverScrollDuration = 0L @@ -39,6 +39,12 @@ constructor( @PanelState private var panelState: Int = STATE_CLOSED private var releaseOverScrollAnimator: Animator? = null + private val qS: QS + get() = qSProvider() + + private val nsslController: NotificationStackScrollLayoutController + get() = nsslControllerProvider() + init { updateResources() configurationController.addCallback( @@ -47,7 +53,9 @@ constructor( updateResources() } }) - dumpManager.registerDumpable(this::dump) + dumpManager.registerDumpable("SplitShadeOverScroller") { printWriter, _ -> + dump(printWriter) + } } private fun updateResources() { @@ -118,7 +126,7 @@ constructor( releaseOverScrollAnimator = null } - private fun dump(pw: PrintWriter, strings: Array<String>) { + private fun dump(pw: PrintWriter) { pw.println( """ SplitShadeOverScroller: @@ -129,15 +137,14 @@ constructor( previousOverscrollAmount: $previousOverscrollAmount dragDownAmount: $dragDownAmount panelState: $panelState - """.trimIndent() - ) + """.trimIndent()) } @AssistedFactory fun interface Factory { fun create( - qS: QS, - nsslController: NotificationStackScrollLayoutController + qSProvider: () -> QS, + nsslControllerProvider: () -> NotificationStackScrollLayoutController ): SplitShadeOverScroller } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index bce5a159f79c..d3837d7347dc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -142,7 +142,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { protected void setEntryPinned( @NonNull HeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) { - mLogger.logSetEntryPinned(headsUpEntry.mEntry.getKey(), isPinned); + mLogger.logSetEntryPinned(headsUpEntry.mEntry, isPinned); NotificationEntry entry = headsUpEntry.mEntry; if (entry.isRowPinned() != isPinned) { entry.setRowPinned(isPinned); @@ -183,7 +183,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { entry.setHeadsUp(false); setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */); EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */); - mLogger.logNotificationActuallyRemoved(entry.getKey()); + mLogger.logNotificationActuallyRemoved(entry); for (OnHeadsUpChangedListener listener : mListeners) { listener.onHeadsUpStateChanged(entry, false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt index 6a74ba957b4b..d7c81af53d8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt @@ -20,6 +20,8 @@ import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.LogLevel.VERBOSE import com.android.systemui.log.dagger.NotificationHeadsUpLog +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject /** Logger for [HeadsUpManager]. */ @@ -56,9 +58,9 @@ class HeadsUpManagerLogger @Inject constructor( }) } - fun logShowNotification(key: String) { + fun logShowNotification(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "show notification $str1" }) @@ -66,16 +68,16 @@ class HeadsUpManagerLogger @Inject constructor( fun logRemoveNotification(key: String, releaseImmediately: Boolean) { buffer.log(TAG, INFO, { - str1 = key + str1 = logKey(key) bool1 = releaseImmediately }, { "remove notification $str1 releaseImmediately: $bool1" }) } - fun logNotificationActuallyRemoved(key: String) { + fun logNotificationActuallyRemoved(entry: NotificationEntry) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey }, { "notification removed $str1 " }) @@ -83,7 +85,7 @@ class HeadsUpManagerLogger @Inject constructor( fun logUpdateNotification(key: String, alert: Boolean, hasEntry: Boolean) { buffer.log(TAG, INFO, { - str1 = key + str1 = logKey(key) bool1 = alert bool2 = hasEntry }, { @@ -91,12 +93,12 @@ class HeadsUpManagerLogger @Inject constructor( }) } - fun logUpdateEntry(key: String, updatePostTime: Boolean) { + fun logUpdateEntry(entry: NotificationEntry, updatePostTime: Boolean) { buffer.log(TAG, INFO, { - str1 = key + str1 = entry.logKey bool1 = updatePostTime }, { - "update entry $key updatePostTime: $bool1" + "update entry $str1 updatePostTime: $bool1" }) } @@ -108,9 +110,9 @@ class HeadsUpManagerLogger @Inject constructor( }) } - fun logSetEntryPinned(key: String, isPinned: Boolean) { + fun logSetEntryPinned(entry: NotificationEntry, isPinned: Boolean) { buffer.log(TAG, VERBOSE, { - str1 = key + str1 = entry.logKey bool1 = isPinned }, { "set entry pinned $str1 pinned: $bool1" diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index 7de4586e1901..bc351427310d 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -27,7 +27,6 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,8 +67,6 @@ import org.mockito.junit.MockitoRule; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper() public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { - private static final int VIEW_WIDTH = 1600; - @Rule public MockitoRule mRule = MockitoJUnit.rule(); @@ -141,7 +138,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { when(mResources.getConfiguration()).thenReturn(mConfiguration); when(mView.getContext()).thenReturn(mContext); when(mView.getResources()).thenReturn(mResources); - when(mView.getWidth()).thenReturn(VIEW_WIDTH); when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class))) .thenReturn(mAdminSecondaryLockScreenController); when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController); @@ -212,49 +208,26 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mUserSwitcherController); } - private void touchDownLeftSide() { + private void touchDown() { mKeyguardSecurityContainerController.mGlobalTouchListener.onTouchEvent( MotionEvent.obtain( /* downTime= */0, /* eventTime= */0, MotionEvent.ACTION_DOWN, - /* x= */VIEW_WIDTH / 3f, - /* y= */0, - /* metaState= */0)); - } - - private void touchDownRightSide() { - mKeyguardSecurityContainerController.mGlobalTouchListener.onTouchEvent( - MotionEvent.obtain( - /* downTime= */0, - /* eventTime= */0, - MotionEvent.ACTION_DOWN, - /* x= */(VIEW_WIDTH / 3f) * 2, + /* x= */0, /* y= */0, /* metaState= */0)); } @Test - public void onInterceptTap_inhibitsFalsingInOneHandedMode() { - when(mView.getMode()).thenReturn(MODE_ONE_HANDED); - when(mView.isOneHandedModeLeftAligned()).thenReturn(true); - - touchDownLeftSide(); - verify(mFalsingCollector, never()).avoidGesture(); - - // Now on the right. - touchDownRightSide(); - verify(mFalsingCollector).avoidGesture(); - - // Move and re-test - reset(mFalsingCollector); - when(mView.isOneHandedModeLeftAligned()).thenReturn(false); + public void onInterceptTap_inhibitsFalsingInSidedSecurityMode() { - // On the right... - touchDownRightSide(); + when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(false); + touchDown(); verify(mFalsingCollector, never()).avoidGesture(); - touchDownLeftSide(); + when(mView.isTouchOnTheOtherSideOfSecurity(any())).thenReturn(true); + touchDown(); verify(mFalsingCollector).avoidGesture(); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index d49f4d8172dc..1b9662ccae0c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -16,6 +16,9 @@ package com.android.keyguard; +import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE; +import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT; +import static android.provider.Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.systemBars; @@ -25,7 +28,9 @@ import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -34,10 +39,10 @@ import static org.mockito.Mockito.when; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Insets; -import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; @@ -70,6 +75,9 @@ import java.util.ArrayList; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper() public class KeyguardSecurityContainerTest extends SysuiTestCase { + + private static final int VIEW_WIDTH = 1600; + private int mScreenWidth; private int mFakeMeasureSpec; @@ -212,14 +220,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { mKeyguardSecurityContainer.updatePositionByTouchX( mKeyguardSecurityContainer.getWidth() - 1f); - verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, - Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT); + verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_RIGHT); verify(mSecurityViewFlipper).setTranslationX( mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth()); mKeyguardSecurityContainer.updatePositionByTouchX(1f); - verify(mGlobalSettings).putInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE, - Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT); + verify(mGlobalSettings).putInt(ONE_HANDED_KEYGUARD_SIDE, ONE_HANDED_KEYGUARD_SIDE_LEFT); verify(mSecurityViewFlipper).setTranslationX(0.0f); } @@ -253,10 +259,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { // THEN views are oriented side by side verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM); - ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById( - R.id.keyguard_bouncer_user_switcher); - assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity) - .isEqualTo(Gravity.LEFT | Gravity.CENTER_VERTICAL); + assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); } @Test @@ -276,10 +279,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { // THEN views are both centered horizontally verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture()); assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL); - ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById( - R.id.keyguard_bouncer_user_switcher); - assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity) - .isEqualTo(Gravity.CENTER_HORIZONTAL); + assertUserSwitcherGravity(Gravity.CENTER_HORIZONTAL); } @Test @@ -310,7 +310,85 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { assertThat(anchor.isClickable()).isTrue(); } + @Test + public void testTouchesAreRecognizedAsBeingOnTheOtherSideOfSecurity() { + setupUserSwitcher(); + setViewWidth(VIEW_WIDTH); + + assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( + touchEventLeftSide())).isTrue(); + assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( + touchEventRightSide())).isFalse(); + + mKeyguardSecurityContainer.handleDoubleTap(touchEventLeftSide()); + // settings should be updated, we need to keep the mock updated as well + when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT); + assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( + touchEventLeftSide())).isFalse(); + assertThat(mKeyguardSecurityContainer.isTouchOnTheOtherSideOfSecurity( + touchEventRightSide())).isTrue(); + } + + @Test + public void testSecuritySwitchesSidesInLandscapeUserSwitcherMode() { + Configuration config = new Configuration(); + config.orientation = Configuration.ORIENTATION_LANDSCAPE; + when(getContext().getResources().getConfiguration()).thenReturn(config); + setupUserSwitcher(); + // check default position + assertSecurityGravity(Gravity.RIGHT | Gravity.BOTTOM); + assertUserSwitcherGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + + reset(mSecurityViewFlipper); + when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams); + // change setting so configuration change triggers position change + when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_LEFT); + mKeyguardSecurityContainer.onConfigurationChanged(new Configuration()); + + // check position after switching + assertSecurityGravity(Gravity.LEFT | Gravity.BOTTOM); + assertUserSwitcherGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); + } + + private void assertUserSwitcherGravity(@Gravity.GravityFlags int gravity) { + ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById( + R.id.keyguard_bouncer_user_switcher); + assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity) + .isEqualTo(gravity); + } + + private void assertSecurityGravity(@Gravity.GravityFlags int gravity) { + verify(mSecurityViewFlipper, atLeastOnce()).setLayoutParams(mLayoutCaptor.capture()); + assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(gravity); + } + + private void setViewWidth(int width) { + mKeyguardSecurityContainer.setRight(width); + mKeyguardSecurityContainer.setLeft(0); + } + + private MotionEvent touchEventLeftSide() { + return MotionEvent.obtain( + /* downTime= */0, + /* eventTime= */0, + MotionEvent.ACTION_DOWN, + /* x= */VIEW_WIDTH / 3f, + /* y= */0, + /* metaState= */0); + } + + private MotionEvent touchEventRightSide() { + return MotionEvent.obtain( + /* downTime= */0, + /* eventTime= */0, + MotionEvent.ACTION_DOWN, + /* x= */(VIEW_WIDTH / 3f) * 2, + /* y= */0, + /* metaState= */0); + } + private void setupUserSwitcher() { + when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_RIGHT); mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER, mGlobalSettings, mFalsingManager, mUserSwitcherController); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java index 3c28d48c2eb5..d334694805fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java @@ -57,6 +57,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; import java.util.concurrent.Executor; @SmallTest @@ -115,7 +116,7 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { mNextAlarmController, mDateFormatUtil, mSensorPrivacyController, - mDreamOverlayNotificationCountProvider, + Optional.of(mDreamOverlayNotificationCountProvider), mZenModeController, mStatusBarWindowStateController); } @@ -231,6 +232,26 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { } @Test + public void testNotificationsIconNotShownWhenCountProviderAbsent() { + DreamOverlayStatusBarViewController controller = new DreamOverlayStatusBarViewController( + mView, + mResources, + mMainExecutor, + mConnectivityManager, + mTouchSession, + mAlarmManager, + mNextAlarmController, + mDateFormatUtil, + mSensorPrivacyController, + Optional.empty(), + mZenModeController, + mStatusBarWindowStateController); + controller.onViewAttached(); + verify(mView, never()).showIcon( + eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any()); + } + + @Test public void testOnViewAttachedShowsPriorityModeIconWhenEnabled() { when(mZenModeController.getZen()).thenReturn( Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java index cefdf283fc7d..dc1ae0e93757 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java @@ -15,6 +15,8 @@ */ package com.android.systemui.dreams; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -23,10 +25,13 @@ import static org.mockito.Mockito.when; import android.app.smartspace.SmartspaceTarget; import android.content.Context; import android.testing.AndroidTestingRunner; +import android.view.View; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dreams.complication.Complication; +import com.android.systemui.dreams.complication.ComplicationViewModel; import com.android.systemui.dreams.smartspace.DreamSmartspaceController; import com.android.systemui.plugins.BcSmartspaceDataPlugin; @@ -55,6 +60,12 @@ public class SmartSpaceComplicationTest extends SysuiTestCase { @Mock private SmartSpaceComplication mComplication; + @Mock + private ComplicationViewModel mComplicationViewModel; + + @Mock + private View mBcSmartspaceView; + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -90,4 +101,13 @@ public class SmartSpaceComplicationTest extends SysuiTestCase { listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target)); verify(mDreamOverlayStateController).addComplication(eq(mComplication)); } + + @Test + public void testGetViewReusesSameView() { + final SmartSpaceComplication complication = new SmartSpaceComplication(getContext(), + mSmartspaceController); + final Complication.ViewHolder viewHolder = complication.createView(mComplicationViewModel); + when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView); + assertEquals(viewHolder.getView(), viewHolder.getView()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java index f00fbe6ac4d7..141a213a5b6a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -480,4 +481,13 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { // hide dialog again mGlobalActionsDialogLite.showOrHideDialog(true, true, null /* view */); } + + @Test + public void testBugreportAction_whenDebugMode_shouldOfferBugreportButtonBeforeProvisioning() { + doReturn(1).when(mGlobalSettings).getInt(anyString(), anyInt()); + + GlobalActionsDialogLite.BugReportAction bugReportAction = + mGlobalActionsDialogLite.makeBugReportActionForTesting(); + assertThat(bugReportAction.showBeforeProvisioning()).isTrue(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index e3b5059131fa..9eaa20c2afed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -32,6 +32,7 @@ import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.Bundle; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -86,6 +87,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { NearbyMediaDevicesManager.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; @@ -110,7 +112,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index feed3347f3e2..2bf5f0fcbfcb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -19,6 +19,9 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -34,10 +37,12 @@ import android.graphics.drawable.Icon; import android.media.AudioManager; import android.media.MediaDescription; import android.media.MediaMetadata; +import android.media.MediaRoute2Info; import android.media.NearbyDevice; import android.media.RoutingSessionInfo; import android.media.session.MediaController; import android.media.session.MediaSessionManager; +import android.os.PowerExemptionManager; import android.os.RemoteException; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; @@ -97,6 +102,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class); private ActivityStarter mStarter = mock(ActivityStarter.class); private AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( @@ -125,7 +131,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; MediaDescription.Builder builder = new MediaDescription.Builder(); @@ -177,7 +183,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.start(mCb); @@ -206,7 +212,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.start(mCb); @@ -511,7 +517,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } @@ -591,4 +597,20 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isTrue(); } + + @Test + public void setTemporaryAllowListExceptionIfNeeded_fromRemoteToBluetooth_addsAllowList() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); + when(mMediaDevice1.getDeviceType()).thenReturn( + MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE); + when(mMediaDevice1.getFeatures()).thenReturn( + ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_AUDIO_PLAYBACK)); + when(mMediaDevice2.getDeviceType()).thenReturn( + MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE); + + mMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); + + verify(mPowerExemptionManager).addToTemporaryAllowList(anyString(), anyInt(), anyString(), + anyLong()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index 6786ad0116ea..c45db05bacee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -29,6 +29,7 @@ import android.media.MediaRoute2Info; import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -84,6 +85,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputDialog mMediaOutputDialog; @@ -103,7 +105,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); @@ -138,16 +140,31 @@ public class MediaOutputDialogTest extends SysuiTestCase { mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK); assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE); + } - mFeatures.clear(); + @Test + public void getStopButtonVisibility_remoteBLEDevice_returnVisible() { when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( mLocalBluetoothLeBroadcast); when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false); when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING); + when(mMediaDevice.isBLEDevice()).thenReturn(true); + assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE); } @Test + public void getStopButtonVisibility_remoteNonBLEDevice_returnGone() { + when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn( + mLocalBluetoothLeBroadcast); + when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false); + when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING); + when(mMediaDevice.isBLEDevice()).thenReturn(false); + + assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE); + } + + @Test public void getStopButtonVisibility_localDevice_returnGone() { mFeatures.add(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index 379bb4fd6336..4534ae6448ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import android.media.AudioManager; import android.media.session.MediaSessionManager; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -70,6 +71,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private MediaOutputGroupDialog mMediaOutputGroupDialog; private MediaOutputController mMediaOutputController; @@ -80,7 +82,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender, mMediaOutputController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt index b9a69bb8641a..1527f0d0d71f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt @@ -25,6 +25,7 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager import android.widget.ImageView import androidx.test.filters.SmallTest import com.android.systemui.R @@ -65,6 +66,8 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { @Mock private lateinit var logger: MediaTttLogger @Mock + private lateinit var accessibilityManager: AccessibilityManager + @Mock private lateinit var windowManager: WindowManager @Mock private lateinit var viewUtil: ViewUtil @@ -88,11 +91,21 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { )).thenReturn(applicationInfo) context.setMockPackageManager(packageManager) + whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())) + .thenReturn(TIMEOUT_MS.toInt()) + fakeClock = FakeSystemClock() fakeExecutor = FakeExecutor(fakeClock) controllerCommon = TestControllerCommon( - context, logger, windowManager, viewUtil, fakeExecutor, tapGestureDetector, powerManager + context, + logger, + windowManager, + viewUtil, + fakeExecutor, + accessibilityManager, + tapGestureDetector, + powerManager ) } @@ -344,6 +357,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { windowManager: WindowManager, viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, + accessibilityManager: AccessibilityManager, tapGestureDetector: TapGestureDetector, powerManager: PowerManager ) : MediaTttChipControllerCommon<ChipInfo>( @@ -352,6 +366,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { windowManager, viewUtil, mainExecutor, + accessibilityManager, tapGestureDetector, powerManager, R.layout.media_ttt_chip @@ -364,7 +379,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } inner class ChipInfo : ChipInfoCommon { - override fun getTimeoutMs() = TIMEOUT_MS + override fun getTimeoutMs() = 1L } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 9edc4f4c71c3..bbc564193080 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -28,6 +28,7 @@ import android.testing.TestableLooper import android.view.View import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager import android.widget.ImageView import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake @@ -65,6 +66,8 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var logger: MediaTttLogger @Mock + private lateinit var accessibilityManager: AccessibilityManager + @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var windowManager: WindowManager @@ -99,6 +102,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { windowManager, viewUtil, FakeExecutor(FakeSystemClock()), + accessibilityManager, TapGestureDetector(context), powerManager, Handler.getMain(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt index a8c72ddfd5d7..7ca0cd34ab26 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -27,6 +27,7 @@ import android.testing.TestableLooper import android.view.View import android.view.ViewGroup import android.view.WindowManager +import android.view.accessibility.AccessibilityManager import android.widget.ImageView import android.widget.TextView import androidx.test.filters.SmallTest @@ -67,6 +68,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Mock private lateinit var logger: MediaTttLogger @Mock + private lateinit var accessibilityManager: AccessibilityManager + @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var windowManager: WindowManager @@ -95,9 +98,12 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { fakeClock = FakeSystemClock() fakeExecutor = FakeExecutor(fakeClock) + uiEventLoggerFake = UiEventLoggerFake() senderUiEventLogger = MediaTttSenderUiEventLogger(uiEventLoggerFake) + whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenReturn(TIMEOUT) + controllerSender = MediaTttChipControllerSender( commandQueue, context, @@ -105,6 +111,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { windowManager, viewUtil, fakeExecutor, + accessibilityManager, TapGestureDetector(context), powerManager, senderUiEventLogger @@ -592,7 +599,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { fakeClock.advanceTime(1000L) controllerSender.removeChip("fakeRemovalReason") - fakeClock.advanceTime(state.state.timeout + 1) + fakeClock.advanceTime(TIMEOUT + 1L) verify(windowManager).removeView(any()) } @@ -615,7 +622,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { fakeClock.advanceTime(1000L) controllerSender.removeChip("fakeRemovalReason") - fakeClock.advanceTime(state.state.timeout + 1) + fakeClock.advanceTime(TIMEOUT + 1L) verify(windowManager).removeView(any()) } @@ -674,6 +681,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { private const val APP_NAME = "Fake app name" private const val OTHER_DEVICE_NAME = "My Tablet" private const val PACKAGE_NAME = "com.android.systemui" +private const val TIMEOUT = 10000 private val routeInfo = MediaRoute2Info.Builder("id", OTHER_DEVICE_NAME) .addFeature("feature") diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt index 9d5099cfafd0..81d5c4d52b74 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt @@ -1,10 +1,10 @@ package com.android.systemui.statusbar -import org.mockito.Mockito.`when` as whenever import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.ScrimController @@ -19,6 +19,7 @@ import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.verifyZeroInteractions +import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -32,6 +33,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var qS: QS @Mock private lateinit var nsslController: NotificationStackScrollLayoutController + @Mock private lateinit var dumpManager: DumpManager private lateinit var overScroller: SplitShadeLockScreenOverScroller @@ -44,11 +46,12 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { overScroller = SplitShadeLockScreenOverScroller( configurationController, + dumpManager, context, scrimController, statusBarStateController, - qS, - nsslController) + { qS }, + { nsslController }) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java index 7d06abf5cd67..3fc0c8176f2f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicPrivacyControllerTest.java @@ -63,7 +63,7 @@ public class DynamicPrivacyControllerTest extends SysuiTestCase { mock(StatusBarKeyguardViewManager.class)); mDynamicPrivacyController.addListener(mListener); // Disable dynamic privacy by default - allowPrivateNotificationsInPublic(true); + allowNotificationsInPublic(false); } @Test @@ -108,24 +108,21 @@ public class DynamicPrivacyControllerTest extends SysuiTestCase { @Test public void dynamicPrivacyOnlyWhenHidingPrivate() { - // Verify that when only hiding notifications, this isn't enabled - allowPrivateNotificationsInPublic(true); - when(mLockScreenUserManager.shouldHideNotifications(any())).thenReturn( - false); - assertFalse("Dynamic privacy shouldn't be enabled when only hiding notifications", + // Verify that when hiding notifications, this isn't enabled + allowNotificationsInPublic(false); + assertFalse("Dynamic privacy shouldn't be enabled when hiding notifications", mDynamicPrivacyController.isDynamicPrivacyEnabled()); - allowPrivateNotificationsInPublic(false); - assertTrue("Should be enabled when hiding notification contents", + allowNotificationsInPublic(true); + assertTrue("Should be enabled whenever notifications are visible", mDynamicPrivacyController.isDynamicPrivacyEnabled()); } private void enableDynamicPrivacy() { - allowPrivateNotificationsInPublic(false); + allowNotificationsInPublic(true); } - private void allowPrivateNotificationsInPublic(boolean allow) { - when(mLockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn( - allow); + private void allowNotificationsInPublic(boolean allow) { + when(mLockScreenUserManager.userAllowsNotificationsInPublic(anyInt())).thenReturn(allow); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java index 0d5a5fe086a3..3f641df376ed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderTest.java @@ -72,32 +72,32 @@ public class HeadsUpViewBinderTest extends SysuiTestCase { }); mViewBinder.bindHeadsUpView(mEntry, null); - verify(mLogger).startBindingHun(eq("key")); + verify(mLogger).startBindingHun(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); callback.get().onBindFinished(mEntry); - verify(mLogger).entryBoundSuccessfully(eq("key")); + verify(mLogger).entryBoundSuccessfully(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); mViewBinder.bindHeadsUpView(mEntry, null); - verify(mLogger).startBindingHun(eq("key")); + verify(mLogger).startBindingHun(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); callback.get().onBindFinished(mEntry); - verify(mLogger).entryBoundSuccessfully(eq("key")); + verify(mLogger).entryBoundSuccessfully(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); mViewBinder.unbindHeadsUpView(mEntry); - verify(mLogger).entryContentViewMarkedFreeable(eq("key")); + verify(mLogger).entryContentViewMarkedFreeable(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); callback.get().onBindFinished(mEntry); - verify(mLogger).entryUnbound(eq("key")); + verify(mLogger).entryUnbound(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); } @@ -111,12 +111,12 @@ public class HeadsUpViewBinderTest extends SysuiTestCase { }); mViewBinder.bindHeadsUpView(mEntry, null); - verify(mLogger).startBindingHun(eq("key")); + verify(mLogger).startBindingHun(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); mViewBinder.abortBindCallback(mEntry); - verify(mLogger).currentOngoingBindingAborted(eq("key")); + verify(mLogger).currentOngoingBindingAborted(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); @@ -135,18 +135,18 @@ public class HeadsUpViewBinderTest extends SysuiTestCase { }); mViewBinder.bindHeadsUpView(mEntry, null); - verify(mLogger).startBindingHun(eq("key")); + verify(mLogger).startBindingHun(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); mViewBinder.unbindHeadsUpView(mEntry); - verify(mLogger).currentOngoingBindingAborted(eq("key")); - verify(mLogger).entryContentViewMarkedFreeable(eq("key")); + verify(mLogger).currentOngoingBindingAborted(eq(mEntry)); + verify(mLogger).entryContentViewMarkedFreeable(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); callback.get().onBindFinished(mEntry); - verify(mLogger).entryUnbound(eq("key")); + verify(mLogger).entryUnbound(eq(mEntry)); verifyNoMoreInteractions(mLogger); clearInvocations(mLogger); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index b1bf971c52fc..f8b39e8cff71 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -43,6 +43,7 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.app.NotificationChannel; +import android.graphics.Color; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; @@ -110,6 +111,28 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test + public void testUpdateBackgroundColors_isRecursive() { + mGroupRow.setTintColor(Color.RED); + mGroupRow.getChildNotificationAt(0).setTintColor(Color.GREEN); + mGroupRow.getChildNotificationAt(1).setTintColor(Color.BLUE); + + assertThat(mGroupRow.getCurrentBackgroundTint()).isEqualTo(Color.RED); + assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint()) + .isEqualTo(Color.GREEN); + assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint()) + .isEqualTo(Color.BLUE); + + mGroupRow.updateBackgroundColors(); + + int resetTint = mGroupRow.getCurrentBackgroundTint(); + assertThat(resetTint).isNotEqualTo(Color.RED); + assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint()) + .isEqualTo(resetTint); + assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint()) + .isEqualTo(resetTint); + } + + @Test public void testSetSensitiveOnNotifRowNotifiesOfHeightChange() throws InterruptedException { // GIVEN a sensitive notification row that's currently redacted measureAndLayout(mNotifRow); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionControllerTest.kt index b24b348ac316..cafe113e7872 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ScrimShadeTransitionControllerTest.kt @@ -5,6 +5,8 @@ import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.StatusBarState +import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent import com.android.systemui.statusbar.policy.FakeConfigurationController @@ -13,6 +15,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -21,6 +24,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { @Mock private lateinit var scrimController: ScrimController @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController private val configurationController = FakeConfigurationController() private lateinit var controller: ScrimShadeTransitionController @@ -31,9 +35,14 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { context.ensureTestableResources() controller = ScrimShadeTransitionController( - configurationController, dumpManager, scrimController, context.resources + configurationController, + dumpManager, + scrimController, + context.resources, + statusBarStateController ) } + @Test fun onPanelExpansionChanged_inSingleShade_setsFractionEqualToEventFraction() { setSplitShadeEnabled(false) @@ -44,7 +53,9 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { } @Test - fun onPanelExpansionChanged_inSplitShade_setsFractionBasedOnDragDownAmount() { + fun onPanelExpansionChanged_inSplitShade_unlockedShade_setsFractionBasedOnDragDownAmount() { + whenever(statusBarStateController.currentOrUpcomingState) + .thenReturn(StatusBarState.SHADE) val scrimShadeTransitionDistance = context.resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance) setSplitShadeEnabled(true) @@ -55,6 +66,54 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { verify(scrimController).setRawPanelExpansionFraction(expectedFraction) } + @Test + fun onPanelExpansionChanged_inSplitShade_largeDragDownAmount_fractionIsNotGreaterThan1() { + whenever(statusBarStateController.currentOrUpcomingState) + .thenReturn(StatusBarState.SHADE) + val scrimShadeTransitionDistance = + context.resources.getDimensionPixelSize(R.dimen.split_shade_scrim_transition_distance) + setSplitShadeEnabled(true) + + controller.onPanelExpansionChanged( + EXPANSION_EVENT.copy(dragDownPxAmount = 100f * scrimShadeTransitionDistance) + ) + + verify(scrimController).setRawPanelExpansionFraction(1f) + } + + @Test + fun onPanelExpansionChanged_inSplitShade_negativeDragDownAmount_fractionIsNotLessThan0() { + whenever(statusBarStateController.currentOrUpcomingState) + .thenReturn(StatusBarState.SHADE) + setSplitShadeEnabled(true) + + controller.onPanelExpansionChanged(EXPANSION_EVENT.copy(dragDownPxAmount = -100f)) + + verify(scrimController).setRawPanelExpansionFraction(0f) + } + + @Test + fun onPanelExpansionChanged_inSplitShade_onLockedShade_setsFractionEqualToEventFraction() { + whenever(statusBarStateController.currentOrUpcomingState) + .thenReturn(StatusBarState.SHADE_LOCKED) + setSplitShadeEnabled(true) + + controller.onPanelExpansionChanged(EXPANSION_EVENT) + + verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction) + } + + @Test + fun onPanelExpansionChanged_inSplitShade_onKeyguard_setsFractionEqualToEventFraction() { + whenever(statusBarStateController.currentOrUpcomingState) + .thenReturn(StatusBarState.KEYGUARD) + setSplitShadeEnabled(true) + + controller.onPanelExpansionChanged(EXPANSION_EVENT) + + verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction) + } + private fun setSplitShadeEnabled(enabled: Boolean) { overrideResource(R.bool.config_use_split_notification_shade, enabled) configurationController.notifyConfigurationChanged() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionControllerTest.kt index c78a2a720d40..85a8c6bf7d95 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/ShadeTransitionControllerTest.kt @@ -4,6 +4,7 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.NotificationPanelViewController @@ -29,6 +30,7 @@ class ShadeTransitionControllerTest : SysuiTestCase() { @Mock private lateinit var noOpOverScroller: NoOpOverScroller @Mock private lateinit var splitShadeOverScroller: SplitShadeOverScroller @Mock private lateinit var scrimShadeTransitionController: ScrimShadeTransitionController + @Mock private lateinit var dumpManager: DumpManager private lateinit var controller: ShadeTransitionController @@ -43,6 +45,7 @@ class ShadeTransitionControllerTest : SysuiTestCase() { ShadeTransitionController( configurationController, panelExpansionStateManager, + dumpManager, context, splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller }, noOpOverScroller, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScrollerTest.kt index 4456207c1184..5ca15bb93d31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScrollerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/shade/transition/SplitShadeOverScrollerTest.kt @@ -43,8 +43,12 @@ class SplitShadeOverScrollerTest : SysuiTestCase() { whenever(nsslController.height).thenReturn(1000) overScroller = SplitShadeOverScroller( - configurationController, dumpManager, context, scrimController, qs, nsslController - ) + configurationController, + dumpManager, + context, + scrimController, + { qs }, + { nsslController }) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java index 424a40058997..b8e25ab43691 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java @@ -106,7 +106,7 @@ public class HeadsUpManagerTest extends AlertingNotificationManagerTest { public void testHunRemovedLogging() { mAlertEntry.mEntry = mEntry; mHeadsUpManager.onAlertEntryRemoved(mAlertEntry); - verify(mLogger, times(1)).logNotificationActuallyRemoved(eq(mEntry.getKey())); + verify(mLogger, times(1)).logNotificationActuallyRemoved(eq(mEntry)); } @Test diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index e37d7b057986..6076eb1f69ee 100644 --- a/services/core/java/com/android/server/am/AppRestrictionController.java +++ b/services/core/java/com/android/server/am/AppRestrictionController.java @@ -1115,6 +1115,14 @@ public final class AppRestrictionController { DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_on_long_running"; /** + * The behavior for an app with a FGS, when the system detects it's running for + * a very long time, should we prompt the user. + * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it. + */ + static final String KEY_BG_PROMPT_FGS_ON_LONG_RUNNING = + DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_on_long_running"; + + /** * The list of packages to be exempted from all these background restrictions. */ static final String KEY_BG_RESTRICTION_EXEMPTED_PACKAGES = @@ -1154,6 +1162,11 @@ public final class AppRestrictionController { static final boolean DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = false; /** + * Default value to {@link #mBgPromptFgsOnLongRunning}. + */ + static final boolean DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING = true; + + /** * Default value to {@link #mBgPromptFgsWithNotiToBgRestricted}. */ final boolean mDefaultBgPromptFgsWithNotiToBgRestricted; @@ -1191,6 +1204,11 @@ public final class AppRestrictionController { volatile boolean mBgPromptFgsWithNotiOnLongRunning; /** + * @see #KEY_BG_PROMPT_FGS_ON_LONG_RUNNING. + */ + volatile boolean mBgPromptFgsOnLongRunning; + + /** * @see #KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED. */ volatile boolean mBgPromptAbusiveAppsToBgRestricted; @@ -1228,6 +1246,9 @@ public final class AppRestrictionController { case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING: updateBgPromptFgsWithNotiOnLongRunning(); break; + case KEY_BG_PROMPT_FGS_ON_LONG_RUNNING: + updateBgPromptFgsOnLongRunning(); + break; case KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED: updateBgPromptAbusiveAppToBgRestricted(); break; @@ -1269,6 +1290,7 @@ public final class AppRestrictionController { updateBgLongFgsNotificationMinimalInterval(); updateBgPromptFgsWithNotiToBgRestricted(); updateBgPromptFgsWithNotiOnLongRunning(); + updateBgPromptFgsOnLongRunning(); updateBgPromptAbusiveAppToBgRestricted(); updateBgRestrictionExemptedPackages(); } @@ -1319,6 +1341,13 @@ public final class AppRestrictionController { DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); } + private void updateBgPromptFgsOnLongRunning() { + mBgPromptFgsOnLongRunning = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_BG_PROMPT_FGS_ON_LONG_RUNNING, + DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING); + } + private void updateBgPromptAbusiveAppToBgRestricted() { mBgPromptAbusiveAppsToBgRestricted = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -1365,6 +1394,14 @@ public final class AppRestrictionController { pw.print('='); pw.println(mBgLongFgsNotificationMinIntervalMs); pw.print(prefix); + pw.print(KEY_BG_PROMPT_FGS_ON_LONG_RUNNING); + pw.print('='); + pw.println(mBgPromptFgsOnLongRunning); + pw.print(prefix); + pw.print(KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); + pw.print('='); + pw.println(mBgPromptFgsWithNotiOnLongRunning); + pw.print(prefix); pw.print(KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED); pw.print('='); pw.println(mBgPromptFgsWithNotiToBgRestricted); @@ -2500,6 +2537,12 @@ public final class AppRestrictionController { ActivityManager.isLowRamDeviceStatic(), mBgController.getRestrictionLevel(uid)); PendingIntent pendingIntent; + if (!mBgController.mConstantsObserver.mBgPromptFgsOnLongRunning) { + if (DEBUG_BG_RESTRICTION_CONTROLLER) { + Slog.i(TAG, "Long-running FGS prompt is disabled."); + } + return; + } if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiOnLongRunning && mBgController.hasForegroundServiceNotifications(packageName, uid)) { if (DEBUG_BG_RESTRICTION_CONTROLLER) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index a2048a347c7c..92a8dcd2ba8f 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -2794,15 +2794,6 @@ public final class ProcessList { } int N = procs.size(); - for (int i = 0; i < N; ++i) { - final ProcessRecord proc = procs.get(i).first; - try { - Process.setProcessFrozen(proc.getPid(), proc.uid, true); - } catch (Exception e) { - Slog.w(TAG, "Unable to freeze " + proc.getPid() + " " + proc.processName); - } - } - for (int i=0; i<N; i++) { final Pair<ProcessRecord, Boolean> proc = procs.get(i); removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second, diff --git a/services/core/java/com/android/server/am/TraceErrorLogger.java b/services/core/java/com/android/server/am/TraceErrorLogger.java index 29a9b5c501c4..ec0587f721d4 100644 --- a/services/core/java/com/android/server/am/TraceErrorLogger.java +++ b/services/core/java/com/android/server/am/TraceErrorLogger.java @@ -16,7 +16,6 @@ package com.android.server.am; -import android.os.Build; import android.os.Trace; import java.util.UUID; @@ -31,7 +30,7 @@ public class TraceErrorLogger { private static final int PLACEHOLDER_VALUE = 1; public boolean isAddErrorIdEnabled() { - return Build.IS_DEBUGGABLE; + return true; } /** diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3551ff91f542..f526960d0ef3 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -86,6 +86,8 @@ import android.net.ipsec.ike.ChildSessionConfiguration; import android.net.ipsec.ike.ChildSessionParams; import android.net.ipsec.ike.IkeSession; import android.net.ipsec.ike.IkeSessionCallback; +import android.net.ipsec.ike.IkeSessionConfiguration; +import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.exceptions.IkeNetworkLostException; @@ -168,9 +170,10 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** @@ -190,11 +193,19 @@ public class Vpn { private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000; // Length of time (in milliseconds) that an app registered for VpnManager events is placed on - // the device idle allowlist each time the a VpnManager event is fired. + // the device idle allowlist each time the VpnManager event is fired. private static final long VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS = 30 * 1000; private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME = Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST; + + /** + * The retries for consecutive failures. + * + * <p>If retries have exceeded the length of this array, the last entry in the array will be + * used as a repeating interval. + */ + private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L}; /** * Largest profile size allowable for Platform VPNs. * @@ -473,6 +484,20 @@ public class Vpn { "Cannot set tunnel's fd as blocking=" + blocking, e); } } + + /** + * Retrieves the next retry delay + * + * <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in + * the array will be used as a repeating interval. + */ + public long getNextRetryDelaySeconds(int retryCount) { + if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) { + return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1]; + } else { + return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount]; + } + } } public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, @@ -1646,7 +1671,9 @@ public class Vpn { for (String app : packageNames) { int uid = getAppUid(app, userId); if (uid != -1) uids.add(uid); - if (Process.isApplicationUid(uid)) { + // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from + // ConnectivityServiceTest. + if (Process.isApplicationUid(uid) && SdkLevel.isAtLeastT()) { uids.add(Process.toSdkSandboxUid(uid)); } } @@ -2603,13 +2630,23 @@ public class Vpn { void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp); - void onChildOpened( - @NonNull Network network, @NonNull ChildSessionConfiguration childConfig); + void onDefaultNetworkLost(@NonNull Network network); + + void onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration); + + void onIkeConnectionInfoChanged( + int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo); - void onChildTransformCreated( - @NonNull Network network, @NonNull IpSecTransform transform, int direction); + void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig); - void onSessionLost(@NonNull Network network, @Nullable Exception exception); + void onChildTransformCreated(int token, @NonNull IpSecTransform transform, int direction); + + void onChildMigrated( + int token, + @NonNull IpSecTransform inTransform, + @NonNull IpSecTransform outTransform); + + void onSessionLost(int token, @Nullable Exception exception); } /** @@ -2640,6 +2677,10 @@ public class Vpn { class IkeV2VpnRunner extends VpnRunner implements IkeV2VpnRunnerCallback { @NonNull private static final String TAG = "IkeV2VpnRunner"; + // 5 seconds grace period before tearing down the IKE Session in case new default network + // will come up + private static final long NETWORK_LOST_TIMEOUT_MS = 5000L; + @NonNull private final IpSecManager mIpSecManager; @NonNull private final Ikev2VpnProfile mProfile; @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback; @@ -2651,24 +2692,60 @@ public class Vpn { * of the mutable Ikev2VpnRunner fields. The Ikev2VpnRunner is built mostly lock-free by * virtue of everything being serialized on this executor. */ - @NonNull private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + @NonNull + private final ScheduledThreadPoolExecutor mExecutor = new ScheduledThreadPoolExecutor(1); + + @Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostTimeout; + @Nullable private ScheduledFuture<?> mScheduledHandleRetryIkeSessionTimeout; /** Signal to ensure shutdown is honored even if a new Network is connected. */ private boolean mIsRunning = true; + /** + * The token used by the primary/current/active IKE session. + * + * <p>This token MUST be updated when the VPN switches to use a new IKE session. + */ + private int mCurrentToken = -1; + @Nullable private IpSecTunnelInterface mTunnelIface; - @Nullable private IkeSession mSession; @Nullable private Network mActiveNetwork; @Nullable private NetworkCapabilities mUnderlyingNetworkCapabilities; @Nullable private LinkProperties mUnderlyingLinkProperties; private final String mSessionKey; + @Nullable private IkeSession mSession; + @Nullable private IkeSessionConnectionInfo mIkeConnectionInfo; + + // mMobikeEnabled can only be updated after IKE AUTH is finished. + private boolean mMobikeEnabled = false; + + /** + * The number of attempts since the last successful connection. + * + * <p>This variable controls the retry delay, and is reset when a new IKE session is + * opened or when there is a new default network. + */ + private int mRetryCount = 0; + IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) { super(TAG); mProfile = profile; mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this, mExecutor); mSessionKey = UUID.randomUUID().toString(); + + // Set the policy so that cancelled tasks will be removed from the work queue + mExecutor.setRemoveOnCancelPolicy(true); + + // Set the policy so that all delayed tasks will not be executed + mExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); + + // To avoid hitting RejectedExecutionException upon shutdown of the mExecutor */ + mExecutor.setRejectedExecutionHandler( + (r, executor) -> { + Log.d(TAG, "Runnable " + r + " rejected by the mExecutor"); + }); } @Override @@ -2707,22 +2784,64 @@ public class Vpn { return Objects.equals(mActiveNetwork, network) && mIsRunning; } + private boolean isActiveToken(int token) { + return (mCurrentToken == token) && mIsRunning; + } + + /** + * Called when an IKE session has been opened + * + * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor + * thread in order to ensure consistency of the Ikev2VpnRunner fields. + */ + public void onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration) { + if (!isActiveToken(token)) { + Log.d(TAG, "onIkeOpened called for obsolete token " + token); + return; + } + + mMobikeEnabled = + ikeConfiguration.isIkeExtensionEnabled( + IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE); + onIkeConnectionInfoChanged(token, ikeConfiguration.getIkeSessionConnectionInfo()); + mRetryCount = 0; + } + + /** + * Called when an IKE session's {@link IkeSessionConnectionInfo} is available or updated + * + * <p>This callback is usually fired when an IKE session has been opened or migrated. + * + * <p>This method is called multiple times over the lifetime of an IkeSession, and MUST run + * on the mExecutor thread in order to ensure consistency of the Ikev2VpnRunner fields. + */ + public void onIkeConnectionInfoChanged( + int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { + if (!isActiveToken(token)) { + Log.d(TAG, "onIkeConnectionInfoChanged called for obsolete token " + token); + return; + } + + // The update on VPN and the IPsec tunnel will be done when migration is fully complete + // in onChildMigrated + mIkeConnectionInfo = ikeConnectionInfo; + } + /** * Called when an IKE Child session has been opened, signalling completion of the startup. * * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor * thread in order to ensure consistency of the Ikev2VpnRunner fields. */ - public void onChildOpened( - @NonNull Network network, @NonNull ChildSessionConfiguration childConfig) { - if (!isActiveNetwork(network)) { - Log.d(TAG, "onOpened called for obsolete network " + network); + public void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig) { + if (!isActiveToken(token)) { + Log.d(TAG, "onChildOpened called for obsolete token " + token); // Do nothing; this signals that either: (1) a new/better Network was found, - // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this - // IKE session was already shut down (exited, or an error was encountered somewhere - // else). In both cases, all resources and sessions are torn down via - // resetIkeState(). + // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in + // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, + // or an error was encountered somewhere else). In both cases, all resources and + // sessions are torn down via resetIkeState(). return; } @@ -2741,6 +2860,11 @@ public class Vpn { dnsAddrStrings.add(addr.getHostAddress()); } + // The actual network of this IKE session has been set up with is + // mIkeConnectionInfo.getNetwork() instead of mActiveNetwork because + // mActiveNetwork might have been updated after the setup was triggered. + final Network network = mIkeConnectionInfo.getNetwork(); + final NetworkAgent networkAgent; final LinkProperties lp; @@ -2783,8 +2907,8 @@ public class Vpn { networkAgent.sendLinkProperties(lp); } catch (Exception e) { - Log.d(TAG, "Error in ChildOpened for network " + network, e); - onSessionLost(network, e); + Log.d(TAG, "Error in ChildOpened for token " + token, e); + onSessionLost(token, e); } } @@ -2792,19 +2916,19 @@ public class Vpn { * Called when an IPsec transform has been created, and should be applied. * * <p>This method is called multiple times over the lifetime of an IkeSession (or default - * network), and is MUST always be called on the mExecutor thread in order to ensure + * network), and MUST always be called on the mExecutor thread in order to ensure * consistency of the Ikev2VpnRunner fields. */ public void onChildTransformCreated( - @NonNull Network network, @NonNull IpSecTransform transform, int direction) { - if (!isActiveNetwork(network)) { - Log.d(TAG, "ChildTransformCreated for obsolete network " + network); + int token, @NonNull IpSecTransform transform, int direction) { + if (!isActiveToken(token)) { + Log.d(TAG, "ChildTransformCreated for obsolete token " + token); // Do nothing; this signals that either: (1) a new/better Network was found, - // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this - // IKE session was already shut down (exited, or an error was encountered somewhere - // else). In both cases, all resources and sessions are torn down via - // resetIkeState(). + // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in + // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, + // or an error was encountered somewhere else). In both cases, all resources and + // sessions are torn down via resetIkeState(). return; } @@ -2813,36 +2937,127 @@ public class Vpn { // them alive for us mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform); } catch (IOException e) { - Log.d(TAG, "Transform application failed for network " + network, e); - onSessionLost(network, e); + Log.d(TAG, "Transform application failed for token " + token, e); + onSessionLost(token, e); + } + } + + /** + * Called when an IPsec transform has been created, and should be re-applied. + * + * <p>This method is called multiple times over the lifetime of an IkeSession (or default + * network), and MUST always be called on the mExecutor thread in order to ensure + * consistency of the Ikev2VpnRunner fields. + */ + public void onChildMigrated( + int token, + @NonNull IpSecTransform inTransform, + @NonNull IpSecTransform outTransform) { + if (!isActiveToken(token)) { + Log.d(TAG, "onChildMigrated for obsolete token " + token); + return; + } + + // The actual network of this IKE session has migrated to is + // mIkeConnectionInfo.getNetwork() instead of mActiveNetwork because mActiveNetwork + // might have been updated after the migration was triggered. + final Network network = mIkeConnectionInfo.getNetwork(); + + try { + synchronized (Vpn.this) { + mConfig.underlyingNetworks = new Network[] {network}; + mNetworkCapabilities = + new NetworkCapabilities.Builder(mNetworkCapabilities) + .setUnderlyingNetworks(Collections.singletonList(network)) + .build(); + mNetworkAgent.setUnderlyingNetworks(Collections.singletonList(network)); + } + + mTunnelIface.setUnderlyingNetwork(network); + + // Transforms do not need to be persisted; the IkeSession will keep them alive for + // us + mIpSecManager.applyTunnelModeTransform( + mTunnelIface, IpSecManager.DIRECTION_IN, inTransform); + mIpSecManager.applyTunnelModeTransform( + mTunnelIface, IpSecManager.DIRECTION_OUT, outTransform); + } catch (IOException e) { + Log.d(TAG, "Transform application failed for token " + token, e); + onSessionLost(token, e); } } /** * Called when a new default network is connected. * - * <p>The Ikev2VpnRunner will unconditionally switch to the new network, killing the old IKE - * state in the process, and starting a new IkeSession instance. + * <p>The Ikev2VpnRunner will unconditionally switch to the new network. If the IKE session + * has mobility, Ikev2VpnRunner will migrate the existing IkeSession to the new network. + * Otherwise, Ikev2VpnRunner will kill the old IKE state, and start a new IkeSession + * instance. * * <p>This method MUST always be called on the mExecutor thread in order to ensure * consistency of the Ikev2VpnRunner fields. */ public void onDefaultNetworkChanged(@NonNull Network network) { - Log.d(TAG, "Starting IKEv2/IPsec session on new network: " + network); + Log.d(TAG, "onDefaultNetworkChanged: " + network); + + // If there is a new default network brought up, cancel the retry task to prevent + // establishing an unnecessary IKE session. + cancelRetryNewIkeSessionFuture(); + + // If there is a new default network brought up, cancel the obsolete reset and retry + // task. + cancelHandleNetworkLostTimeout(); + + if (!mIsRunning) { + Log.d(TAG, "onDefaultNetworkChanged after exit"); + return; // VPN has been shut down. + } + + mActiveNetwork = network; + mRetryCount = 0; + + startOrMigrateIkeSession(network); + } + + /** + * Start a new IKE session. + * + * <p>This method MUST always be called on the mExecutor thread in order to ensure + * consistency of the Ikev2VpnRunner fields. + * + * @param underlyingNetwork if the value is {@code null}, which means there is no active + * network can be used, do nothing and return immediately. Otherwise, use the + * given network to start a new IKE session. + */ + private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) { + if (underlyingNetwork == null) { + Log.d(TAG, "There is no active network for starting an IKE session"); + return; + } try { - if (!mIsRunning) { - Log.d(TAG, "onDefaultNetworkChanged after exit"); - return; // VPN has been shut down. + if (mSession != null && mMobikeEnabled) { + // IKE session can schedule a migration event only when IKE AUTH is finished + // and mMobikeEnabled is true. + Log.d( + TAG, + "Migrate IKE Session with token " + + mCurrentToken + + " to network " + + underlyingNetwork); + mSession.setNetwork(underlyingNetwork); + return; } + Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); + // Clear mInterface to prevent Ikev2VpnRunner being cleared when // interfaceRemoved() is called. mInterface = null; // Without MOBIKE, we have no way to seamlessly migrate. Close on old // (non-default) network, and start the new one. resetIkeState(); - mActiveNetwork = network; // Get Ike options from IkeTunnelConnectionParams if it's available in the // profile. @@ -2852,12 +3067,12 @@ public class Vpn { final ChildSessionParams childSessionParams; if (ikeTunConnParams != null) { final IkeSessionParams.Builder builder = new IkeSessionParams.Builder( - ikeTunConnParams.getIkeSessionParams()).setNetwork(network); + ikeTunConnParams.getIkeSessionParams()).setNetwork(underlyingNetwork); ikeSessionParams = builder.build(); childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams(); } else { ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams( - mContext, mProfile, network); + mContext, mProfile, underlyingNetwork); childSessionParams = VpnIkev2Utils.buildChildSessionParams( mProfile.getAllowedAlgorithms()); } @@ -2865,29 +3080,50 @@ public class Vpn { // TODO: Remove the need for adding two unused addresses with // IPsec tunnels. final InetAddress address = InetAddress.getLocalHost(); + + // When onChildOpened is called and transforms are applied, it is + // guaranteed that the underlying network is still "network", because the + // all the network switch events will be deferred before onChildOpened is + // called. Thus it is safe to build a mTunnelIface before IKE setup. mTunnelIface = mIpSecManager.createIpSecTunnelInterface( - address /* unused */, - address /* unused */, - network); + address /* unused */, address /* unused */, underlyingNetwork); NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName()); - mSession = mIkev2SessionCreator.createIkeSession( - mContext, - ikeSessionParams, - childSessionParams, - mExecutor, - new VpnIkev2Utils.IkeSessionCallbackImpl( - TAG, IkeV2VpnRunner.this, network), - new VpnIkev2Utils.ChildSessionCallbackImpl( - TAG, IkeV2VpnRunner.this, network)); - Log.d(TAG, "Ike Session started for network " + network); + final int token = ++mCurrentToken; + mSession = + mIkev2SessionCreator.createIkeSession( + mContext, + ikeSessionParams, + childSessionParams, + mExecutor, + new VpnIkev2Utils.IkeSessionCallbackImpl( + TAG, IkeV2VpnRunner.this, token), + new VpnIkev2Utils.ChildSessionCallbackImpl( + TAG, IkeV2VpnRunner.this, token)); + Log.d(TAG, "IKE session started for token " + token); } catch (Exception e) { - Log.i(TAG, "Setup failed for network " + network + ". Aborting", e); - onSessionLost(network, e); + Log.i(TAG, "Setup failed for token " + mCurrentToken + ". Aborting", e); + onSessionLost(mCurrentToken, e); } } + private void scheduleRetryNewIkeSession() { + final long retryDelay = mDeps.getNextRetryDelaySeconds(mRetryCount++); + Log.d(TAG, "Retry new IKE session after " + retryDelay + " seconds."); + // If the default network is lost during the retry delay, the mActiveNetwork will be + // null, and the new IKE session won't be established until there is a new default + // network bringing up. + mScheduledHandleRetryIkeSessionTimeout = + mExecutor.schedule(() -> { + startOrMigrateIkeSession(mActiveNetwork); + + // Reset mScheduledHandleRetryIkeSessionTimeout since it's already run on + // executor thread. + mScheduledHandleRetryIkeSessionTimeout = null; + }, retryDelay, TimeUnit.SECONDS); + } + /** Called when the NetworkCapabilities of underlying network is changed */ public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) { mUnderlyingNetworkCapabilities = nc; @@ -2898,6 +3134,99 @@ public class Vpn { mUnderlyingLinkProperties = lp; } + /** + * Handles loss of the default underlying network + * + * <p>If the IKE Session has mobility, Ikev2VpnRunner will schedule a teardown event with a + * delay so that the IKE Session can migrate if a new network is available soon. Otherwise, + * Ikev2VpnRunner will kill the IKE session and reset the VPN. + * + * <p>This method MUST always be called on the mExecutor thread in order to ensure + * consistency of the Ikev2VpnRunner fields. + */ + public void onDefaultNetworkLost(@NonNull Network network) { + // If the default network is torn down, there is no need to call + // startOrMigrateIkeSession() since it will always check if there is an active network + // can be used or not. + cancelRetryNewIkeSessionFuture(); + + if (!isActiveNetwork(network)) { + Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network); + + // Do nothing; this signals that either: (1) a new/better Network was found, + // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in + // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, + // or an error was encountered somewhere else). In both cases, all resources and + // sessions are torn down via resetIkeState(). + return; + } else { + mActiveNetwork = null; + } + + if (mScheduledHandleNetworkLostTimeout != null + && !mScheduledHandleNetworkLostTimeout.isCancelled() + && !mScheduledHandleNetworkLostTimeout.isDone()) { + final IllegalStateException exception = + new IllegalStateException( + "Found a pending mScheduledHandleNetworkLostTimeout"); + Log.i( + TAG, + "Unexpected error in onDefaultNetworkLost. Tear down session", + exception); + handleSessionLost(exception, network); + return; + } + + if (mSession != null && mMobikeEnabled) { + Log.d( + TAG, + "IKE Session has mobility. Delay handleSessionLost for losing network " + + network + + " on session with token " + + mCurrentToken); + + // Delay the teardown in case a new network will be available soon. For example, + // during handover between two WiFi networks, Android will disconnect from the + // first WiFi and then connects to the second WiFi. + mScheduledHandleNetworkLostTimeout = + mExecutor.schedule( + () -> { + handleSessionLost(null, network); + }, + NETWORK_LOST_TIMEOUT_MS, + TimeUnit.MILLISECONDS); + } else { + Log.d(TAG, "Call handleSessionLost for losing network " + network); + handleSessionLost(null, network); + } + } + + private void cancelHandleNetworkLostTimeout() { + if (mScheduledHandleNetworkLostTimeout != null + && !mScheduledHandleNetworkLostTimeout.isDone()) { + // It does not matter what to put in #cancel(boolean), because it is impossible + // that the task tracked by mScheduledHandleNetworkLostTimeout is + // in-progress since both that task and onDefaultNetworkChanged are submitted to + // mExecutor who has only one thread. + Log.d(TAG, "Cancel the task for handling network lost timeout"); + mScheduledHandleNetworkLostTimeout.cancel(false /* mayInterruptIfRunning */); + mScheduledHandleNetworkLostTimeout = null; + } + } + + private void cancelRetryNewIkeSessionFuture() { + if (mScheduledHandleRetryIkeSessionTimeout != null + && !mScheduledHandleRetryIkeSessionTimeout.isDone()) { + // It does not matter what to put in #cancel(boolean), because it is impossible + // that the task tracked by mScheduledHandleRetryIkeSessionTimeout is + // in-progress since both that task and onDefaultNetworkChanged are submitted to + // mExecutor who has only one thread. + Log.d(TAG, "Cancel the task for handling new ike session timeout"); + mScheduledHandleRetryIkeSessionTimeout.cancel(false /* mayInterruptIfRunning */); + mScheduledHandleRetryIkeSessionTimeout = null; + } + } + /** Marks the state as FAILED, and disconnects. */ private void markFailedAndDisconnect(Exception exception) { synchronized (Vpn.this) { @@ -2916,18 +3245,28 @@ public class Vpn { * <p>This method MUST always be called on the mExecutor thread in order to ensure * consistency of the Ikev2VpnRunner fields. */ - public void onSessionLost(@NonNull Network network, @Nullable Exception exception) { - if (!isActiveNetwork(network)) { - Log.d(TAG, "onSessionLost() called for obsolete network " + network); + public void onSessionLost(int token, @Nullable Exception exception) { + Log.d(TAG, "onSessionLost() called for token " + token); + + if (!isActiveToken(token)) { + Log.d(TAG, "onSessionLost() called for obsolete token " + token); // Do nothing; this signals that either: (1) a new/better Network was found, - // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this - // IKE session was already shut down (exited, or an error was encountered somewhere - // else). In both cases, all resources and sessions are torn down via - // onSessionLost() and resetIkeState(). + // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in + // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, + // or an error was encountered somewhere else). In both cases, all resources and + // sessions are torn down via resetIkeState(). return; } + handleSessionLost(exception, mActiveNetwork); + } + + private void handleSessionLost(@Nullable Exception exception, @Nullable Network network) { + // Cancel mScheduledHandleNetworkLostTimeout if the session it is going to terminate is + // already terminated due to other failures. + cancelHandleNetworkLostTimeout(); + synchronized (Vpn.this) { if (exception instanceof IkeProtocolException) { final IkeProtocolException ikeException = (IkeProtocolException) exception; @@ -2947,7 +3286,7 @@ public class Vpn { VpnManager.ERROR_CLASS_NOT_RECOVERABLE, ikeException.getErrorType(), getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -2965,7 +3304,7 @@ public class Vpn { VpnManager.ERROR_CLASS_RECOVERABLE, ikeException.getErrorType(), getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -2984,7 +3323,7 @@ public class Vpn { VpnManager.ERROR_CLASS_RECOVERABLE, VpnManager.ERROR_CODE_NETWORK_LOST, getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -2999,7 +3338,7 @@ public class Vpn { VpnManager.ERROR_CLASS_RECOVERABLE, VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST, getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -3013,7 +3352,7 @@ public class Vpn { VpnManager.ERROR_CLASS_RECOVERABLE, VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT, getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -3027,7 +3366,7 @@ public class Vpn { VpnManager.ERROR_CLASS_RECOVERABLE, VpnManager.ERROR_CODE_NETWORK_IO, getPackage(), mSessionKey, makeVpnProfileStateLocked(), - mActiveNetwork, + network, getRedactedNetworkCapabilitiesOfUnderlyingNetwork( mUnderlyingNetworkCapabilities), getRedactedLinkPropertiesOfUnderlyingNetwork( @@ -3037,15 +3376,16 @@ public class Vpn { } else if (exception != null) { Log.wtf(TAG, "onSessionLost: exception = " + exception); } + + scheduleRetryNewIkeSession(); } - mActiveNetwork = null; mUnderlyingNetworkCapabilities = null; mUnderlyingLinkProperties = null; // Close all obsolete state, but keep VPN alive incase a usable network comes up. // (Mirrors VpnService behavior) - Log.d(TAG, "Resetting state for network: " + network); + Log.d(TAG, "Resetting state for token: " + mCurrentToken); synchronized (Vpn.this) { // Since this method handles non-fatal errors only, set mInterface to null to @@ -3090,6 +3430,8 @@ public class Vpn { mSession.kill(); // Kill here to make sure all resources are released immediately mSession = null; } + mIkeConnectionInfo = null; + mMobikeEnabled = false; } /** diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java index 17058282d947..857c86de57ca 100644 --- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java +++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java @@ -68,6 +68,7 @@ import android.net.ipsec.ike.IkeRfc822AddrIdentification; import android.net.ipsec.ike.IkeSaProposal; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; +import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTrafficSelector; import android.net.ipsec.ike.TunnelModeChildSessionParams; @@ -107,6 +108,7 @@ public class VpnIkev2Utils { new IkeSessionParams.Builder(context) .setServerHostname(profile.getServerAddr()) .setNetwork(network) + .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) .setLocalIdentification(localId) .setRemoteIdentification(remoteId); setIkeAuth(profile, ikeOptionsBuilder); @@ -298,72 +300,79 @@ public class VpnIkev2Utils { static class IkeSessionCallbackImpl implements IkeSessionCallback { private final String mTag; private final Vpn.IkeV2VpnRunnerCallback mCallback; - private final Network mNetwork; + private final int mToken; - IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) { + IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) { mTag = tag; mCallback = callback; - mNetwork = network; + mToken = token; } @Override public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) { - Log.d(mTag, "IkeOpened for network " + mNetwork); - // Nothing to do here. + Log.d(mTag, "IkeOpened for token " + mToken); + mCallback.onIkeOpened(mToken, ikeSessionConfig); } @Override public void onClosed() { - Log.d(mTag, "IkeClosed for network " + mNetwork); - mCallback.onSessionLost(mNetwork, null); // Server requested session closure. Retry? + Log.d(mTag, "IkeClosed for token " + mToken); + mCallback.onSessionLost(mToken, null); // Server requested session closure. Retry? } @Override public void onClosedExceptionally(@NonNull IkeException exception) { - Log.d(mTag, "IkeClosedExceptionally for network " + mNetwork, exception); - mCallback.onSessionLost(mNetwork, exception); + Log.d(mTag, "IkeClosedExceptionally for token " + mToken, exception); + mCallback.onSessionLost(mToken, exception); } @Override public void onError(@NonNull IkeProtocolException exception) { - Log.d(mTag, "IkeError for network " + mNetwork, exception); + Log.d(mTag, "IkeError for token " + mToken, exception); // Non-fatal, log and continue. } + + @Override + public void onIkeSessionConnectionInfoChanged( + @NonNull IkeSessionConnectionInfo connectionInfo) { + Log.d(mTag, "onIkeSessionConnectionInfoChanged for token " + mToken); + mCallback.onIkeConnectionInfoChanged(mToken, connectionInfo); + } } static class ChildSessionCallbackImpl implements ChildSessionCallback { private final String mTag; private final Vpn.IkeV2VpnRunnerCallback mCallback; - private final Network mNetwork; + private final int mToken; - ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) { + ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) { mTag = tag; mCallback = callback; - mNetwork = network; + mToken = token; } @Override public void onOpened(@NonNull ChildSessionConfiguration childConfig) { - Log.d(mTag, "ChildOpened for network " + mNetwork); - mCallback.onChildOpened(mNetwork, childConfig); + Log.d(mTag, "ChildOpened for token " + mToken); + mCallback.onChildOpened(mToken, childConfig); } @Override public void onClosed() { - Log.d(mTag, "ChildClosed for network " + mNetwork); - mCallback.onSessionLost(mNetwork, null); + Log.d(mTag, "ChildClosed for token " + mToken); + mCallback.onSessionLost(mToken, null); } @Override public void onClosedExceptionally(@NonNull IkeException exception) { - Log.d(mTag, "ChildClosedExceptionally for network " + mNetwork, exception); - mCallback.onSessionLost(mNetwork, exception); + Log.d(mTag, "ChildClosedExceptionally for token " + mToken, exception); + mCallback.onSessionLost(mToken, exception); } @Override public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) { - Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; network " + mNetwork); - mCallback.onChildTransformCreated(mNetwork, transform, direction); + Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; token " + mToken); + mCallback.onChildTransformCreated(mToken, transform, direction); } @Override @@ -371,8 +380,15 @@ public class VpnIkev2Utils { // Nothing to be done; no references to the IpSecTransform are held by the // Ikev2VpnRunner (or this callback class), and this transform will be closed by the // IKE library. - Log.d(mTag, - "ChildTransformDeleted; Direction: " + direction + "; for network " + mNetwork); + Log.d(mTag, "ChildTransformDeleted; Direction: " + direction + "; for token " + mToken); + } + + @Override + public void onIpSecTransformsMigrated( + @NonNull IpSecTransform inIpSecTransform, + @NonNull IpSecTransform outIpSecTransform) { + Log.d(mTag, "ChildTransformsMigrated; token " + mToken); + mCallback.onChildMigrated(mToken, inIpSecTransform, outIpSecTransform); } } @@ -390,7 +406,7 @@ public class VpnIkev2Utils { @Override public void onAvailable(@NonNull Network network) { - Log.d(mTag, "Starting IKEv2/IPsec session on new network: " + network); + Log.d(mTag, "onAvailable called for network: " + network); mExecutor.execute(() -> mCallback.onDefaultNetworkChanged(network)); } @@ -412,8 +428,8 @@ public class VpnIkev2Utils { @Override public void onLost(@NonNull Network network) { - Log.d(mTag, "Tearing down; lost network: " + network); - mExecutor.execute(() -> mCallback.onSessionLost(network, null)); + Log.d(mTag, "onLost called for network: " + network); + mExecutor.execute(() -> mCallback.onDefaultNetworkLost(network)); } } diff --git a/services/core/java/com/android/server/devicestate/DeviceState.java b/services/core/java/com/android/server/devicestate/DeviceState.java index 78d55b92eb80..f8d4b8fffd03 100644 --- a/services/core/java/com/android/server/devicestate/DeviceState.java +++ b/services/core/java/com/android/server/devicestate/DeviceState.java @@ -18,6 +18,7 @@ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE; import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE; +import static android.view.Display.DEFAULT_DISPLAY; import android.annotation.IntDef; import android.annotation.IntRange; @@ -48,9 +49,16 @@ public final class DeviceState { */ public static final int FLAG_CANCEL_OVERRIDE_REQUESTS = 1 << 0; + /** + * Flag that indicates this device state is inaccessible for applications to be placed in. This + * could be a device-state where the {@link DEFAULT_DISPLAY} is not enabled. + */ + public static final int FLAG_APP_INACCESSIBLE = 1 << 1; + /** @hide */ @IntDef(prefix = {"FLAG_"}, flag = true, value = { FLAG_CANCEL_OVERRIDE_REQUESTS, + FLAG_APP_INACCESSIBLE }) @Retention(RetentionPolicy.SOURCE) public @interface DeviceStateFlags {} @@ -97,7 +105,8 @@ public final class DeviceState { @Override public String toString() { - return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\'' + '}'; + return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\'' + + ", app_accessible=" + !hasFlag(FLAG_APP_INACCESSIBLE) + "}"; } @Override diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java index 03e18a04c2d5..8e00ccf68fb1 100644 --- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java @@ -40,6 +40,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; +import android.os.SystemProperties; +import android.os.Trace; import android.util.Slog; import android.util.SparseArray; @@ -144,15 +146,30 @@ public final class DeviceStateManagerService extends SystemService { private Set<Integer> mDeviceStatesAvailableForAppRequests; + @VisibleForTesting + interface SystemPropertySetter { + void setDebugTracingDeviceStateProperty(String value); + } + @NonNull + private final SystemPropertySetter mSystemPropertySetter; + public DeviceStateManagerService(@NonNull Context context) { this(context, DeviceStatePolicy.Provider .fromResources(context.getResources()) .instantiate(context)); } + private DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) { + this(context, policy, (value) -> { + SystemProperties.set("debug.tracing.device_state", value); + }); + } + @VisibleForTesting - DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) { + DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy, + @NonNull SystemPropertySetter systemPropertySetter) { super(context); + mSystemPropertySetter = systemPropertySetter; // We use the DisplayThread because this service indirectly drives // display (on/off) and window (position) events through its callbacks. DisplayThread displayThread = DisplayThread.get(); @@ -462,6 +479,10 @@ public final class DeviceStateManagerService extends SystemService { FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_STATE_CHANGED, newState.getIdentifier(), !mCommittedState.isPresent()); + String traceString = newState.getIdentifier() + ":" + newState.getName(); + Trace.instantForTrack( + Trace.TRACE_TAG_SYSTEM_SERVER, "DeviceStateChanged", traceString); + mSystemPropertySetter.setDebugTracingDeviceStateProperty(traceString); mCommittedState = Optional.of(newState); mPendingState = Optional.empty(); diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java index 9fddc76b78c3..181c39ee50b5 100644 --- a/services/core/java/com/android/server/pm/AppsFilterImpl.java +++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java @@ -418,7 +418,9 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, } else if (changed) { invalidateCache("grantImplicitAccess: " + recipientUid + " -> " + visibleUid); } - onChanged(); + if (changed) { + onChanged(); + } return changed; } diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 30de9ba638cc..259ca655d2b9 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -2686,7 +2686,7 @@ public class ComputerEngine implements Computer { if (Process.isSdkSandboxUid(callingUid)) { int clientAppUid = Process.getAppUidForSdkSandboxUid(callingUid); // SDK sandbox should be able to see it's client app - if (clientAppUid == UserHandle.getUid(userId, ps.getAppId())) { + if (ps != null && clientAppUid == UserHandle.getUid(userId, ps.getAppId())) { return false; } } @@ -2698,7 +2698,7 @@ public class ComputerEngine implements Computer { final boolean callerIsInstantApp = instantAppPkgName != null; if (ps == null) { // pretend the application exists, but, needs to be filtered - return callerIsInstantApp; + return callerIsInstantApp || Process.isSdkSandboxUid(callingUid); } // if the target and caller are the same application, don't filter if (isCallerSameApp(ps.getPackageName(), callingUid)) { @@ -3089,6 +3089,19 @@ public class ComputerEngine implements Computer { } public boolean filterAppAccess(int uid, int callingUid) { + if (Process.isSdkSandboxUid(uid)) { + // Sdk sandbox instance should be able to see itself. + if (callingUid == uid) { + return false; + } + final int clientAppUid = Process.getAppUidForSdkSandboxUid(uid); + // Client app of this sdk sandbox process should be able to see it. + if (clientAppUid == uid) { + return false; + } + // Nobody else should be able to see the sdk sandbox process. + return true; + } final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); final Object setting = mSettings.getSettingBase(appId); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4f8c792d3b49..94e8ec5c434d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2859,12 +2859,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDexOptHelper.performPackageDexOptUpgradeIfNeeded(); } - private void notifyPackageUseInternal(String packageName, int reason) { long time = System.currentTimeMillis(); - commitPackageStateMutation(null, packageName, packageState -> { - packageState.setLastPackageUsageTime(reason, time); - }); + synchronized (mLock) { + final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName); + if (pkgSetting == null) { + return; + } + pkgSetting.getPkgState().setLastPackageUsageTimeInMills(reason, time); + } } /*package*/ DexManager getDexManager() { diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index cc1c943c2540..0ae92b4ee846 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -911,6 +911,11 @@ final class DefaultPermissionGrantPolicy { grantSystemFixedPermissionsToSystemPackage(pm, MidiManager.BLUETOOTH_MIDI_SERVICE_PACKAGE, userId, NEARBY_DEVICES_PERMISSIONS); + + // Ad Service + String commonServiceAction = "android.adservices.AD_SERVICES_COMMON_SERVICE"; + grantPermissionsToSystemPackage(pm, getDefaultSystemHandlerServicePackage(pm, + commonServiceAction, userId), userId, NOTIFICATION_PERMISSIONS); } private String getDefaultSystemHandlerActivityPackageForCategory(PackageManagerWrapper pm, diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java index 88b4a94f7027..03e568c4599e 100644 --- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java @@ -413,8 +413,8 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu return result; } mContext.getSystemService(AppOpsManager.class).noteOpNoThrow( - AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, uid, packageName, - attributionTag, reason); + AppOpsManager.OP_RECORD_AUDIO_HOTWORD, uid, packageName, attributionTag, + reason); return result; } } diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java index 7bd720acc799..5251fe026a9b 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java @@ -79,7 +79,10 @@ public class PackageStateUnserialized { return this; } getLastPackageUsageTimeInMills()[reason] = time; - mPackageSetting.onChanged(); + // TODO(b/236180425): This method does not notify snapshot changes because it's called too + // frequently, causing too many re-takes. This should be moved to a separate data structure + // or merged with the general UsageStats to avoid tracking heavily mutated data in the + // package data snapshot. return this; } diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java index 17a5fd07f920..9b7d19a725d1 100644 --- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java +++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java @@ -95,6 +95,7 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, private static final String DATA_CONFIG_FILE_PATH = "system/devicestate/"; private static final String CONFIG_FILE_NAME = "device_state_configuration.xml"; private static final String FLAG_CANCEL_OVERRIDE_REQUESTS = "FLAG_CANCEL_OVERRIDE_REQUESTS"; + private static final String FLAG_APP_INACCESSIBLE = "FLAG_APP_INACCESSIBLE"; /** Interface that allows reading the device state configuration. */ interface ReadableConfig { @@ -145,6 +146,9 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, case FLAG_CANCEL_OVERRIDE_REQUESTS: flags |= DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS; break; + case FLAG_APP_INACCESSIBLE: + flags |= DeviceState.FLAG_APP_INACCESSIBLE; + break; default: Slog.w(TAG, "Parsed unknown flag with name: " + configFlagString); diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index 78b1c20ac4b2..d79837be3583 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -61,12 +61,11 @@ final class Vibration { IGNORED_BACKGROUND, IGNORED_UNKNOWN_VIBRATION, IGNORED_UNSUPPORTED, - IGNORED_FOR_ALARM, IGNORED_FOR_EXTERNAL, + IGNORED_FOR_HIGHER_IMPORTANCE, IGNORED_FOR_ONGOING, IGNORED_FOR_POWER, IGNORED_FOR_RINGER_MODE, - IGNORED_FOR_RINGTONE, IGNORED_FOR_SETTINGS, IGNORED_SUPERSEDED, } diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index f0911ca62027..5ac2f4f27452 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -713,14 +713,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { case IGNORED_ERROR_APP_OPS: Slog.w(TAG, "Would be an error: vibrate from uid " + uid); break; - case IGNORED_FOR_ALARM: + case IGNORED_FOR_EXTERNAL: if (DEBUG) { - Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); + Slog.d(TAG, "Ignoring incoming vibration for current external vibration"); } break; - case IGNORED_FOR_EXTERNAL: + case IGNORED_FOR_HIGHER_IMPORTANCE: if (DEBUG) { - Slog.d(TAG, "Ignoring incoming vibration for current external vibration"); + Slog.d(TAG, "Ignoring incoming vibration in favor of ongoing vibration" + + " with higher importance"); } break; case IGNORED_FOR_ONGOING: @@ -734,12 +735,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { + attrs); } break; - case IGNORED_FOR_RINGTONE: - if (DEBUG) { - Slog.d(TAG, "Ignoring incoming vibration in favor of ringtone vibration"); - } - break; - default: if (DEBUG) { Slog.d(TAG, "Vibration for uid=" + uid + " and with attrs=" + attrs @@ -812,20 +807,43 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return null; } - if (currentVibration.attrs.getUsage() == VibrationAttributes.USAGE_ALARM) { - return Vibration.Status.IGNORED_FOR_ALARM; - } - - if (currentVibration.attrs.getUsage() == VibrationAttributes.USAGE_RINGTONE) { - return Vibration.Status.IGNORED_FOR_RINGTONE; + int currentUsage = currentVibration.attrs.getUsage(); + int newUsage = vib.attrs.getUsage(); + if (getVibrationImportance(currentUsage) > getVibrationImportance(newUsage)) { + // Current vibration has higher importance than this one and should not be cancelled. + return Vibration.Status.IGNORED_FOR_HIGHER_IMPORTANCE; } if (currentVibration.isRepeating()) { + // Current vibration is repeating, assume it's more important. return Vibration.Status.IGNORED_FOR_ONGOING; } + return null; } + private static int getVibrationImportance(@VibrationAttributes.Usage int usage) { + switch (usage) { + case VibrationAttributes.USAGE_RINGTONE: + return 5; + case VibrationAttributes.USAGE_ALARM: + return 4; + case VibrationAttributes.USAGE_NOTIFICATION: + return 3; + case VibrationAttributes.USAGE_COMMUNICATION_REQUEST: + case VibrationAttributes.USAGE_ACCESSIBILITY: + return 2; + case VibrationAttributes.USAGE_HARDWARE_FEEDBACK: + case VibrationAttributes.USAGE_PHYSICAL_EMULATION: + return 1; + case VibrationAttributes.USAGE_MEDIA: + case VibrationAttributes.USAGE_TOUCH: + case VibrationAttributes.USAGE_UNKNOWN: + default: + return 0; + } + } + /** * Check if given vibration should be ignored by this service. * diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java index dd0ec948aa3a..43d62aaa120a 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java @@ -21,6 +21,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.os.AsyncTask; +import android.os.Trace; import android.os.UserHandle; import android.util.Slog; import android.webkit.UserPackage; @@ -265,10 +266,12 @@ class WebViewUpdateServiceImpl { // Either the current relro creation isn't done yet, or the new relro creatioin // hasn't kicked off yet (the last relro creation used an out-of-date WebView). webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO; - Slog.e(TAG, "Timed out waiting for relro creation, relros started " + String timeoutError = "Timed out waiting for relro creation, relros started " + mNumRelroCreationsStarted + " relros finished " + mNumRelroCreationsFinished - + " package dirty? " + mWebViewPackageDirty); + + " package dirty? " + mWebViewPackageDirty; + Slog.e(TAG, timeoutError); + Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, timeoutError); } } if (!webViewReady) Slog.w(TAG, "creating relro file timed out"); diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index 3b4aa8e6b701..4b8a5b7fcf56 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -853,6 +853,8 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { windowInfo.title = "Splitscreen Divider"; } else if (window.mIsPIPMenu) { windowInfo.title = "Picture-in-Picture menu"; + // Set it to true to be consistent with the legacy implementation. + windowInfo.inPictureInPicture = true; } return windowInfo; } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b3b392c149a1..b6870f5e035b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2467,8 +2467,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (!newTask && taskSwitch && processRunning && !activityCreated && task.intent != null && mActivityComponent.equals(task.intent.getComponent())) { final ActivityRecord topAttached = task.getActivity(ActivityRecord::attachedToProcess); - if (topAttached != null && topAttached.isSnapshotCompatible(snapshot)) { - return STARTING_WINDOW_TYPE_SNAPSHOT; + if (topAttached != null) { + if (topAttached.isSnapshotCompatible(snapshot) + // This trampoline must be the same rotation. + && mDisplayContent.getDisplayRotation().rotationForOrientation(mOrientation, + mDisplayContent.getRotation()) == snapshot.getRotation()) { + return STARTING_WINDOW_TYPE_SNAPSHOT; + } + // No usable snapshot. And a splash screen may also be weird because an existing + // activity may be shown right after the trampoline is finished. + return STARTING_WINDOW_TYPE_NONE; } } final boolean isActivityHome = isActivityTypeHome(); @@ -8174,7 +8182,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A resolvedBounds.set(containingBounds); final float letterboxAspectRatioOverride = - mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); + mLetterboxUiController.getFixedOrientationLetterboxAspectRatio(); final float desiredAspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds); @@ -8727,18 +8735,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Returns the min aspect ratio of this activity. */ private float getMinAspectRatio() { - float infoAspectRatio = info.getMinAspectRatio(getRequestedOrientation()); - // Complying with the CDD 7.1.1.2 requirement for unresizble apps: - // https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio - return infoAspectRatio < 1f && info.resizeMode == RESIZE_MODE_UNRESIZEABLE - // TODO(233582832): Consider removing fixed-orientation condition. - // Some apps switching from tablet to phone layout at the certain size - // threshold. This may lead to flickering on tablets in landscape orientation - // if an app sets orientation to portrait dynamically because of aspect ratio - // restriction applied here. - && getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED - ? mLetterboxUiController.getDefaultMinAspectRatioForUnresizableApps() - : infoAspectRatio; + return info.getMinAspectRatio(getRequestedOrientation()); } /** diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 7bc551b2aacc..b76582fcf3b9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2179,14 +2179,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { : null; mTaskSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront", false /* forceNonResizable */); - - final ActivityRecord topActivity = task.getTopNonFinishingActivity(); - if (topActivity != null) { - - // We are reshowing a task, use a starting window to hide the initial draw delay - // so the transition can start earlier. - topActivity.showStartingWindow(true /* taskSwitch */); - } } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 863faa190692..84740683f6aa 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1434,10 +1434,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mUserLeaving = true; } - task.mTransitionController.requestTransitionIfNeeded(TRANSIT_TO_FRONT, - 0 /* flags */, task, task /* readyGroupRef */, - options != null ? options.getRemoteTransition() : null, - null /* displayChange */); + final Transition newTransition = task.mTransitionController.isShellTransitionsEnabled() + ? task.mTransitionController.isCollecting() ? null + : task.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null; + task.mTransitionController.collect(task); reason = reason + " findTaskToMoveToFront"; boolean reparented = false; if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { @@ -1480,6 +1480,17 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, mRootWindowContainer.getDefaultTaskDisplayArea(), currentRootTask, forceNonResizeable); + if (r != null) { + // Use a starting window to reduce the transition latency for reshowing the task. + // Note that with shell transition, this should be executed before requesting + // transition to avoid delaying the starting window. + r.showStartingWindow(true /* taskSwitch */); + } + if (newTransition != null) { + task.mTransitionController.requestStartTransition(newTransition, task, + options != null ? options.getRemoteTransition() : null, + null /* displayChange */); + } } finally { mUserLeaving = false; } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 3f31ad503c01..53f2c7146656 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -314,6 +314,10 @@ public class AppTransition implements Dump { setAppTransitionState(APP_STATE_TIMEOUT); } + @ColorInt int getNextAppTransitionBackgroundColor() { + return mNextAppTransitionBackgroundColor; + } + HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) { AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( container.hashCode()); diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 3d661222d226..fb9d7e602210 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -116,7 +116,6 @@ public class AppTransitionController { private final DisplayContent mDisplayContent; private final WallpaperController mWallpaperControllerLocked; private RemoteAnimationDefinition mRemoteAnimationDefinition = null; - private static final int KEYGUARD_GOING_AWAY_ANIMATION_DURATION = 400; private static final int TYPE_NONE = 0; private static final int TYPE_ACTIVITY = 1; @@ -727,14 +726,17 @@ public class AppTransitionController { */ private void overrideWithRemoteAnimationIfSet(@Nullable ActivityRecord animLpActivity, @TransitionOldType int transit, ArraySet<Integer> activityTypes) { + RemoteAnimationAdapter adapter = null; if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) { // The crash transition has higher priority than any involved remote animations. - return; - } - final RemoteAnimationAdapter adapter = - getRemoteAnimationOverride(animLpActivity, transit, activityTypes); - if (adapter != null - && mDisplayContent.mAppTransition.getRemoteAnimationController() == null) { + } else if (AppTransition.isKeyguardGoingAwayTransitOld(transit)) { + adapter = mRemoteAnimationDefinition != null + ? mRemoteAnimationDefinition.getAdapter(transit, activityTypes) + : null; + } else if (mDisplayContent.mAppTransition.getRemoteAnimationController() == null) { + adapter = getRemoteAnimationOverride(animLpActivity, transit, activityTypes); + } + if (adapter != null) { mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(adapter); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2ea6ce53caa2..ad3b8ee119d3 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -130,7 +130,6 @@ import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY; import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA; import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION; import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS; -import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -757,8 +756,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG && mImeLayeringTarget != null && !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME) - && mImeLayeringTarget.isAnimating(PARENTS | TRANSITION, - ANIMATION_TYPE_APP_TRANSITION)) { + && !mImeLayeringTarget.isVisibleRequested()) { return false; } @@ -5414,7 +5412,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp SurfaceControl[] findRoundedCornerOverlays() { List<SurfaceControl> roundedCornerOverlays = new ArrayList<>(); for (WindowToken token : mTokenMap.values()) { - if (token.mRoundedCornerOverlay) { + if (token.mRoundedCornerOverlay && token.isVisible()) { roundedCornerOverlays.add(token.mSurfaceControl); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 5c1fc653586e..d3af7d2a19e4 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1523,13 +1523,14 @@ public class DisplayPolicy { */ void simulateLayoutDisplay(DisplayFrames displayFrames) { final InsetsStateController controller = mDisplayContent.getInsetsStateController(); + sTmpClientFrames.attachedFrame = null; for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) { final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i); mWindowLayout.computeFrames(win.mAttrs.forRotation(displayFrames.mRotation), displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe, displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH, - UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), - null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames); + UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), win.mGlobalScale, + sTmpClientFrames); final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources(); final InsetsState state = displayFrames.mInsetsState; for (int index = sources.size() - 1; index >= 0; index--) { @@ -1541,13 +1542,14 @@ public class DisplayPolicy { } void updateInsetsSourceFramesExceptIme(DisplayFrames displayFrames) { + sTmpClientFrames.attachedFrame = null; for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) { final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i); mWindowLayout.computeFrames(win.mAttrs.forRotation(displayFrames.mRotation), displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe, displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH, - UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), - null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames); + UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), win.mGlobalScale, + sTmpClientFrames); win.updateSourceFrame(sTmpClientFrames.frame); } } @@ -1577,7 +1579,7 @@ public class DisplayPolicy { displayFrames = win.getDisplayFrames(displayFrames); final WindowManager.LayoutParams attrs = win.mAttrs.forRotation(displayFrames.mRotation); - final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null; + sTmpClientFrames.attachedFrame = attached != null ? attached.getFrame() : null; // If this window has different LayoutParams for rotations, we cannot trust its requested // size. Because it might have not sent its requested size for the new rotation. @@ -1587,8 +1589,7 @@ public class DisplayPolicy { mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe, win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight, - win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale, - sTmpClientFrames); + win.getRequestedVisibilities(), win.mGlobalScale, sTmpClientFrames); win.setFrames(sTmpClientFrames, win.mRequestedWidth, win.mRequestedHeight); } diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index 2d227b66b3ce..08715b160b9a 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -37,11 +37,6 @@ final class LetterboxConfiguration { */ static final float MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.0f; - // Min allowed aspect ratio for unresizable apps which is used when an app doesn't specify - // android:minAspectRatio in accordance with the CDD 7.1.1.2 requirement: - // https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio - static final float MIN_UNRESIZABLE_ASPECT_RATIO = 4 / 3f; - /** Enum for Letterbox background type. */ @Retention(RetentionPolicy.SOURCE) @IntDef({LETTERBOX_BACKGROUND_SOLID_COLOR, LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND, @@ -109,9 +104,7 @@ final class LetterboxConfiguration { // MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored. private float mFixedOrientationLetterboxAspectRatio; - // Default min aspect ratio for unresizable apps which is used when an app doesn't specify - // android:minAspectRatio in accordance with the CDD 7.1.1.2 requirement: - // https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio + // Default min aspect ratio for unresizable apps that are eligible for the size compat mode. private float mDefaultMinAspectRatioForUnresizableApps; // Corners radius for activities presented in the letterbox mode, values < 0 will be ignored. @@ -250,13 +243,7 @@ final class LetterboxConfiguration { } /** - * Resets the min aspect ratio for unresizable apps which is used when an app doesn't specify - * {@code android:minAspectRatio} to {@link - * R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps}. - * - * @throws AssertionError if {@link - * R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps} is < {@link - * #MIN_UNRESIZABLE_ASPECT_RATIO}. + * Resets the min aspect ratio for unresizable apps that are eligible for size compat mode. */ void resetDefaultMinAspectRatioForUnresizableApps() { setDefaultMinAspectRatioForUnresizableApps(mContext.getResources().getFloat( @@ -264,25 +251,16 @@ final class LetterboxConfiguration { } /** - * Gets the min aspect ratio for unresizable apps which is used when an app doesn't specify - * {@code android:minAspectRatio}. + * Gets the min aspect ratio for unresizable apps that are eligible for size compat mode. */ float getDefaultMinAspectRatioForUnresizableApps() { return mDefaultMinAspectRatioForUnresizableApps; } /** - * Overrides the min aspect ratio for unresizable apps which is used when an app doesn't - * specify {@code android:minAspectRatio}. - * - * @throws AssertionError if given value is < {@link #MIN_UNRESIZABLE_ASPECT_RATIO}. + * Overrides the min aspect ratio for unresizable apps that are eligible for size compat mode. */ void setDefaultMinAspectRatioForUnresizableApps(float aspectRatio) { - if (aspectRatio < MIN_UNRESIZABLE_ASPECT_RATIO) { - throw new AssertionError( - "Unexpected min aspect ratio for unresizable apps, it should be <= " - + MIN_UNRESIZABLE_ASPECT_RATIO + " but was " + aspectRatio); - } mDefaultMinAspectRatioForUnresizableApps = aspectRatio; } diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index df9a87ea1ab0..f849d2886ba1 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -28,6 +28,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; import static com.android.server.wm.LetterboxConfiguration.letterboxBackgroundTypeToString; import android.annotation.Nullable; @@ -211,10 +212,19 @@ final class LetterboxUiController { : mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(); } - float getDefaultMinAspectRatioForUnresizableApps() { + float getFixedOrientationLetterboxAspectRatio() { + return mActivityRecord.shouldCreateCompatDisplayInsets() + ? getDefaultMinAspectRatioForUnresizableApps() + : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); + } + + private float getDefaultMinAspectRatioForUnresizableApps() { if (!mLetterboxConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled() || mActivityRecord.getDisplayContent() == null) { - return mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps(); + return mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps() + > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO + ? mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps() + : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); } int dividerWindowWidth = @@ -226,10 +236,10 @@ final class LetterboxUiController { // Getting the same aspect ratio that apps get in split screen. Rect bounds = new Rect(mActivityRecord.getDisplayContent().getBounds()); if (bounds.width() >= bounds.height()) { - bounds.inset(/* dx */ dividerSize, /* dy */ 0); + bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); bounds.right = bounds.centerX(); } else { - bounds.inset(/* dx */ 0, /* dy */ dividerSize); + bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); bounds.bottom = bounds.centerY(); } return computeAspectRatio(bounds); diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index 878413cb9d78..ad158c7b45b9 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -22,6 +22,7 @@ import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Point; @@ -431,6 +432,7 @@ class RemoteAnimationController implements DeathRecipient { final WindowContainer mWindowContainer; final Rect mStartBounds; final boolean mShowBackdrop; + @ColorInt int mBackdropColor = 0; private @RemoteAnimationTarget.Mode int mMode = RemoteAnimationTarget.MODE_CHANGING; RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds, @@ -456,6 +458,10 @@ class RemoteAnimationController implements DeathRecipient { } } + void setBackDropColor(@ColorInt int backdropColor) { + mBackdropColor = backdropColor; + } + RemoteAnimationTarget createRemoteAnimationTarget() { if (mAdapter == null || mAdapter.mCapturedFinishCallback == null @@ -510,6 +516,12 @@ class RemoteAnimationController implements DeathRecipient { } @Override + @ColorInt + public int getBackgroundColor() { + return mRecord.mBackdropColor; + } + + @Override public boolean getShowBackground() { return mShowBackdrop; } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index e4337f238498..db730e0cb368 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1239,11 +1239,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } @Override - void scheduleAnimation() { - mWmService.scheduleAnimationLocked(); - } - - @Override protected void removeChild(DisplayContent dc) { super.removeChild(dc); if (mTopFocusedDisplayId == dc.getDisplayId()) { diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 2ef19321d958..f80e732c8212 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -102,6 +102,7 @@ class ScreenRotationAnimation { private SurfaceControl mEnterBlackFrameLayer; /** This layer contains the actual screenshot that is to be faded out. */ private SurfaceControl mScreenshotLayer; + private SurfaceControl[] mRoundedCornerOverlay; /** * Only used for screen rotation and not custom animations. Layered behind all other layers * to avoid showing any "empty" spots @@ -151,6 +152,11 @@ class ScreenRotationAnimation { final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270; mOriginalWidth = flipped ? height : width; mOriginalHeight = flipped ? width : height; + final int logicalWidth = displayInfo.logicalWidth; + final int logicalHeight = displayInfo.logicalHeight; + final boolean isSizeChanged = + logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight + && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight); mSurfaceRotationAnimationController = new SurfaceRotationAnimationController(); // Check whether the current screen contains any secure content. @@ -159,18 +165,23 @@ class ScreenRotationAnimation { final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); try { - SurfaceControl.LayerCaptureArgs args = + SurfaceControl.LayerCaptureArgs.Builder builder = new SurfaceControl.LayerCaptureArgs.Builder(displayContent.getSurfaceControl()) .setCaptureSecureLayers(true) .setAllowProtected(true) - .setSourceCrop(new Rect(0, 0, width, height)) - // Exclude rounded corner overlay from screenshot buffer. Rounded - // corner overlay windows are un-rotated during rotation animation - // for a seamless transition. - .setExcludeLayers(displayContent.findRoundedCornerOverlays()) - .build(); + .setSourceCrop(new Rect(0, 0, width, height)); + + if (isSizeChanged) { + mRoundedCornerOverlay = displayContent.findRoundedCornerOverlays(); + } else { + // Exclude rounded corner overlay from screenshot buffer. Rounded + // corner overlay windows are un-rotated during rotation animation + // for a seamless transition. + builder.setExcludeLayers(displayContent.findRoundedCornerOverlays()); + } + SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = - SurfaceControl.captureLayers(args); + SurfaceControl.captureLayers(builder.build()); if (screenshotBuffer == null) { Slog.w(TAG, "Unable to take screenshot of display " + displayId); return; @@ -232,6 +243,14 @@ class ScreenRotationAnimation { t.show(mScreenshotLayer); t.show(mBackColorSurface); + if (mRoundedCornerOverlay != null) { + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.hide(sc); + } + } + } + } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate freeze surface", e); } @@ -240,10 +259,7 @@ class ScreenRotationAnimation { // the new logical display size. Currently pending transaction and RWC#mDisplayTransaction // are merged to global transaction, so it can be synced with display change when calling // DisplayManagerInternal#performTraversal(transaction). - final int logicalWidth = displayInfo.logicalWidth; - final int logicalHeight = displayInfo.logicalHeight; - if (logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight - && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight)) { + if (mScreenshotLayer != null && isSizeChanged) { displayContent.getPendingTransaction().setGeometry(mScreenshotLayer, new Rect(0, 0, mOriginalWidth, mOriginalHeight), new Rect(0, 0, logicalWidth, logicalHeight), Surface.ROTATION_0); @@ -472,6 +488,14 @@ class ScreenRotationAnimation { } mBackColorSurface = null; } + if (mRoundedCornerOverlay != null) { + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.show(sc); + } + } + mRoundedCornerOverlay = null; + } t.apply(); } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 30b50839cd35..ff6a45423084 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -195,27 +195,28 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Rect outAttachedFrame) { return mService.addWindow(this, window, attrs, viewVisibility, displayId, UserHandle.getUserId(mUid), requestedVisibilities, outInputChannel, outInsetsState, - outActiveControls); + outActiveControls, outAttachedFrame); } @Override public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Rect outAttachedFrame) { return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId, - requestedVisibilities, outInputChannel, outInsetsState, outActiveControls); + requestedVisibilities, outInputChannel, outInsetsState, outActiveControls, + outAttachedFrame); } @Override public int addToDisplayWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs, - int viewVisibility, int displayId, InsetsState outInsetsState) { + int viewVisibility, int displayId, InsetsState outInsetsState, Rect outAttachedFrame) { return mService.addWindow(this, window, attrs, viewVisibility, displayId, UserHandle.getUserId(mUid), mDummyRequestedVisibilities, null /* outInputChannel */, - outInsetsState, mDummyControls); + outInsetsState, mDummyControls, outAttachedFrame); } @Override @@ -250,6 +251,11 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } @Override + public boolean cancelDraw(IWindow window) { + return mService.cancelDraw(this, window); + } + + @Override public int relayout(IWindow window, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java index 68dbb0607ac1..0bb773ae5e41 100644 --- a/services/core/java/com/android/server/wm/StartingSurfaceController.java +++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java @@ -158,14 +158,13 @@ public class StartingSurfaceController { + topFullscreenActivity); return null; } - if (topFullscreenActivity.getWindowConfiguration().getRotation() - != taskSnapshot.getRotation()) { + if (activity.mDisplayContent.getRotation() != taskSnapshot.getRotation()) { // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible // that the activity will be updated to the same rotation as the snapshot. Since // the transition is not started yet, fixed rotation transform needs to be applied // earlier to make the snapshot show in a rotated container. activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation( - topFullscreenActivity, false /* checkOpening */); + activity, false /* checkOpening */); } mService.mAtmService.mTaskOrganizerController.addStartingWindow(task, activity, 0 /* launchTheme */, taskSnapshot); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index fc1b89348c25..3d127742d7bd 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1858,6 +1858,11 @@ class Task extends TaskFragment { if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) { nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds(); } + // Only restore to the last non-fullscreen bounds when the requested override bounds + // have not been explicitly set already. + nextPersistTaskBounds &= + (getRequestedOverrideConfiguration().windowConfiguration.getBounds() == null + || getRequestedOverrideConfiguration().windowConfiguration.getBounds().isEmpty()); if (!prevPersistTaskBounds && nextPersistTaskBounds && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) { // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop. @@ -3619,30 +3624,35 @@ class Task extends TaskFragment { } @Override + String toFullString() { + final StringBuilder sb = new StringBuilder(192); + sb.append(this); + sb.setLength(sb.length() - 1); // Remove tail '}'. + sb.append(" U="); + sb.append(mUserId); + final Task rootTask = getRootTask(); + if (rootTask != this) { + sb.append(" rootTaskId="); + sb.append(rootTask.mTaskId); + } + sb.append(" visible="); + sb.append(shouldBeVisible(null /* starting */)); + sb.append(" visibleRequested="); + sb.append(isVisibleRequested()); + sb.append(" mode="); + sb.append(windowingModeToString(getWindowingMode())); + sb.append(" translucent="); + sb.append(isTranslucent(null /* starting */)); + sb.append(" sz="); + sb.append(getChildCount()); + sb.append('}'); + return sb.toString(); + } + + @Override public String toString() { + if (stringName != null) return stringName; StringBuilder sb = new StringBuilder(128); - if (stringName != null) { - sb.append(stringName); - sb.append(" U="); - sb.append(mUserId); - final Task rootTask = getRootTask(); - if (rootTask != this) { - sb.append(" rootTaskId="); - sb.append(rootTask.mTaskId); - } - sb.append(" visible="); - sb.append(shouldBeVisible(null /* starting */)); - sb.append(" visibleRequested="); - sb.append(isVisibleRequested()); - sb.append(" mode="); - sb.append(windowingModeToString(getWindowingMode())); - sb.append(" translucent="); - sb.append(isTranslucent(null /* starting */)); - sb.append(" sz="); - sb.append(getChildCount()); - sb.append('}'); - return sb.toString(); - } sb.append("Task{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" #"); @@ -3657,11 +3667,9 @@ class Task extends TaskFragment { } else if (affinityIntent != null && affinityIntent.getComponent() != null) { sb.append(" aI="); sb.append(affinityIntent.getComponent().flattenToShortString()); - } else { - sb.append(" ??"); } - stringName = sb.toString(); - return toString(); + sb.append('}'); + return stringName = sb.toString(); } /** @@ -4427,13 +4435,13 @@ class Task extends TaskFragment { : WINDOWING_MODE_FULLSCREEN; } if (currentMode == WINDOWING_MODE_PINNED) { + // In the case that we've disabled affecting the SysUI flags as a part of seamlessly + // transferring the transform on the leash to the task, reset this state once we're + // moving out of pip + setCanAffectSystemUiFlags(true); mRootWindowContainer.notifyActivityPipModeChanged(this, null); } if (likelyResolvedMode == WINDOWING_MODE_PINNED) { - // In the case that we've disabled affecting the SysUI flags as a part of seamlessly - // transferring the transform on the leash to the task, reset this state once we've - // actually entered pip - setCanAffectSystemUiFlags(true); if (taskDisplayArea.getRootPinnedTask() != null) { // Can only have 1 pip at a time, so replace an existing pip taskDisplayArea.getRootPinnedTask().dismissPip(); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 02e796904b16..36464b824437 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -1937,7 +1937,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { continue; } final Task rootTask = child.asTask(); - pw.println(doublePrefix + "* " + rootTask); + pw.println(doublePrefix + "* " + rootTask.toFullString()); rootTask.dump(pw, triplePrefix, dumpAll); } } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 391077636654..61e484aaa5b5 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2581,6 +2581,32 @@ class TaskFragment extends WindowContainer<WindowContainer> { return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds(); } + String toFullString() { + final StringBuilder sb = new StringBuilder(128); + sb.append(this); + sb.setLength(sb.length() - 1); // Remove tail '}'. + if (mTaskFragmentOrganizerUid != INVALID_UID) { + sb.append(" organizerUid="); + sb.append(mTaskFragmentOrganizerUid); + } + if (mTaskFragmentOrganizerProcessName != null) { + sb.append(" organizerProc="); + sb.append(mTaskFragmentOrganizerProcessName); + } + if (mAdjacentTaskFragment != null) { + sb.append(" adjacent="); + sb.append(mAdjacentTaskFragment); + } + sb.append('}'); + return sb.toString(); + } + + @Override + public String toString() { + return "TaskFragment{" + Integer.toHexString(System.identityHashCode(this)) + + " mode=" + WindowConfiguration.windowingModeToString(getWindowingMode()) + "}"; + } + boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) { boolean printed = false; @@ -2619,7 +2645,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { } void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) { - pw.print(prefix); pw.print("* "); pw.println(this); + pw.print(prefix); pw.print("* "); pw.println(toFullString()); final Rect bounds = getRequestedOverrideBounds(); if (!bounds.isEmpty()) { pw.println(prefix + " mBounds=" + bounds); @@ -2640,10 +2666,11 @@ class TaskFragment extends WindowContainer<WindowContainer> { final String doublePrefix = prefix + " "; for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowContainer<?> child = mChildren.get(i); - pw.println(prefix + "* " + child); + final TaskFragment tf = child.asTaskFragment(); + pw.println(prefix + "* " + (tf != null ? tf.toFullString() : child)); // Only dump non-activity because full activity info is already printed by // RootWindowContainer#dumpActivities. - if (child.asActivityRecord() == null) { + if (tf != null) { child.dump(pw, doublePrefix, dumpAll); } } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 814656db9fa0..534616fb7207 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -47,6 +47,7 @@ import android.graphics.RenderNode; import android.hardware.HardwareBuffer; import android.os.Environment; import android.os.Handler; +import android.os.Trace; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; @@ -391,8 +392,10 @@ class TaskSnapshotController { SurfaceControl.ScreenshotHardwareBuffer createTaskSnapshot(@NonNull Task task, TaskSnapshot.Builder builder) { Point taskSize = new Point(); + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "createTaskSnapshot"); final SurfaceControl.ScreenshotHardwareBuffer taskSnapshot = createTaskSnapshot(task, mHighResTaskSnapshotScale, builder.getPixelFormat(), taskSize, builder); + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); builder.setTaskSize(taskSize); return taskSnapshot; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index cfc4db969a6f..66cc216fd0e2 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2694,9 +2694,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * will be applied. */ void scheduleAnimation() { - if (mParent != null) { - mParent.scheduleAnimation(); - } + mWmService.scheduleAnimationLocked(); } /** @@ -2949,11 +2947,15 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) { // Here we load App XML in order to read com.android.R.styleable#Animation_showBackdrop. boolean showBackdrop = false; + // Optionally set backdrop color if App explicitly provides it through + // {@link Activity#overridePendingTransition(int, int, int)}. + @ColorInt int backdropColor = 0; if (controller.isFromActivityEmbedding()) { final int animAttr = AppTransition.mapOpenCloseTransitTypes(transit, enter); final Animation a = animAttr != 0 ? appTransition.loadAnimationAttr(lp, animAttr, transit) : null; showBackdrop = a != null && a.getShowBackdrop(); + backdropColor = appTransition.getNextAppTransitionBackgroundColor(); } final Rect localBounds = new Rect(mTmpRect); localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y); @@ -2961,6 +2963,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< controller.createRemoteAnimationRecord( this, mTmpPoint, localBounds, screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null), showBackdrop); + if (backdropColor != 0) { + adapters.setBackDropColor(backdropColor); + } if (!isChanging) { adapters.setMode(enter ? RemoteAnimationTarget.MODE_OPENING diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a48140eb0e04..ae616551958c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -89,6 +89,7 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_RELAUNCH; import static android.view.WindowManagerGlobal.ADD_OKAY; +import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; @@ -1445,7 +1446,7 @@ public class WindowManagerService extends IWindowManager.Stub public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility, int displayId, int requestUserId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { + InsetsSourceControl[] outActiveControls, Rect outAttachedFrame) { Arrays.fill(outActiveControls, null); int[] appOp = new int[1]; final boolean isRoundedCornerOverlay = (attrs.privateFlags @@ -1860,6 +1861,13 @@ public class WindowManagerService extends IWindowManager.Stub outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal()); getInsetsSourceControls(win, outActiveControls); + + if (win.mLayoutAttached) { + outAttachedFrame.set(win.getParentWindow().getCompatFrame()); + } else { + // Make this invalid which indicates a null attached frame. + outAttachedFrame.set(0, 0, -1, -1); + } } Binder.restoreCallingIdentity(origId); @@ -2212,6 +2220,20 @@ public class WindowManagerService extends IWindowManager.Stub == PackageManager.PERMISSION_GRANTED; } + /** + * Returns whether this window can proceed with drawing or needs to retry later. + */ + public boolean cancelDraw(Session session, IWindow client) { + synchronized (mGlobalLock) { + final WindowState win = windowForClientLocked(session, client, false); + if (win == null) { + return false; + } + + return win.cancelAndRedraw(); + } + } + public int relayoutWindow(Session session, IWindow client, LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, @@ -2228,6 +2250,11 @@ public class WindowManagerService extends IWindowManager.Stub if (win == null) { return 0; } + + if (win.cancelAndRedraw()) { + result |= RELAYOUT_RES_CANCEL_AND_REDRAW; + } + final DisplayContent displayContent = win.getDisplayContent(); final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); @@ -2530,6 +2557,7 @@ public class WindowManagerService extends IWindowManager.Stub win.mLastSeqIdSentToRelayout = win.mSyncSeqId; outSyncIdBundle.putInt("seqid", win.mSyncSeqId); + win.mAlreadyRequestedSync = true; } else { outSyncIdBundle.putInt("seqid", -1); } @@ -6041,9 +6069,7 @@ public class WindowManagerService extends IWindowManager.Stub /** Note that Locked in this case is on mLayoutToAnim */ void scheduleAnimationLocked() { - if (mAnimator != null) { - mAnimator.scheduleAnimation(); - } + mAnimator.scheduleAnimation(); } boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 02f056cd33af..ff43a96d6afc 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -1370,9 +1370,10 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" be ignored and framework implementation will determine aspect ratio."); pw.println(" --minAspectRatioForUnresizable aspectRatio"); pw.println(" Default min aspect ratio for unresizable apps which is used when an"); - pw.println(" app doesn't specify android:minAspectRatio. An exception will be"); - pw.println(" thrown if aspectRatio < " - + LetterboxConfiguration.MIN_UNRESIZABLE_ASPECT_RATIO); + pw.println(" app is eligible for the size compat mode. If aspectRatio <= " + + LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO); + pw.println(" both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will"); + pw.println(" be ignored and framework implementation will determine aspect ratio."); pw.println(" --cornerRadius radius"); pw.println(" Corners radius for activities in the letterbox mode. If radius < 0,"); pw.println(" both it and R.integer.config_letterboxActivityCornersRadius will be"); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b4ec3479c756..6728e63d055f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -391,6 +391,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ int mSyncSeqId = 0; int mLastSeqIdSentToRelayout = 0; + boolean mAlreadyRequestedSync; /** * {@code true} when the client was still drawing for sync when the sync-set was finished or @@ -809,7 +810,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP }; private final Consumer<SurfaceControl.Transaction> mSetSurfacePositionConsumer = t -> { - if (mSurfaceControl != null && mSurfaceControl.isValid()) { + // Only apply the position to the surface when there's no leash created. + if (mSurfaceControl != null && mSurfaceControl.isValid() && !mSurfaceAnimator.hasLeash()) { t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y); } }; @@ -879,7 +881,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * {@link InsetsStateController#notifyInsetsChanged}. */ boolean isReadyToDispatchInsetsState() { - return isVisibleRequested() && mFrozenInsetsState == null; + final boolean visible = shouldCheckTokenVisibleRequested() + ? isVisibleRequested() : isVisible(); + return visible && mFrozenInsetsState == null; } void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, @@ -1244,7 +1248,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mSession.windowAddedLocked(); } - boolean updateGlobalScale() { + void updateGlobalScale() { if (hasCompatScale()) { if (mOverrideScale != 1f) { mGlobalScale = mToken.hasSizeCompatBounds() @@ -1254,11 +1258,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mGlobalScale = mToken.getSizeCompatScale(); } mInvGlobalScale = 1f / mGlobalScale; - return true; + return; } mGlobalScale = mInvGlobalScale = 1f; - return false; } /** @@ -1511,23 +1514,23 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean dragResizingChanged = isDragResizeChanged() && !isDragResizingChangeReported(); + final boolean attachedFrameChanged = LOCAL_LAYOUT + && mLayoutAttached && getParentWindow().frameChanged(); + if (DEBUG) { Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged + " dragResizingChanged=" + dragResizingChanged + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame); } - // We update mLastFrame always rather than in the conditional with the last inset - // variables, because mFrameSizeChanged only tracks the width and height changing. - updateLastFrames(); - // Add a window that is using blastSync to the resizing list if it hasn't been reported // already. This because the window is waiting on a finishDrawing from the client. if (didFrameInsetsChange || configChanged || insetsChanged || dragResizingChanged - || shouldSendRedrawForSync()) { + || shouldSendRedrawForSync() + || attachedFrameChanged) { ProtoLog.v(WM_DEBUG_RESIZE, "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b", this, mWindowFrames.getInsetsChangedInfo(), @@ -1583,6 +1586,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + private boolean frameChanged() { + return !mWindowFrames.mFrame.equals(mWindowFrames.mLastFrame); + } + boolean getOrientationChanging() { // In addition to the local state flag, we must also consider the difference in the last // reported configuration vs. the current state. If the client code has not been informed of @@ -3834,6 +3841,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mInvGlobalScale != 1.0f && hasCompatScale()) { outFrames.displayFrame.scale(mInvGlobalScale); } + if (mLayoutAttached) { + if (outFrames.attachedFrame == null) { + outFrames.attachedFrame = new Rect(); + } + outFrames.attachedFrame.set(getParentWindow().getCompatFrame()); + } // Note: in the cases where the window is tied to an activity, we should not send a // configuration update when the window has requested to be hidden. Doing so can lead to @@ -3885,6 +3898,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mDragResizingChangeReported = true; mWindowFrames.clearReportResizeHints(); + // We update mLastFrame always rather than in the conditional with the last inset + // variables, because mFrameSizeChanged only tracks the width and height changing. + updateLastFrames(); + final int prevRotation = mLastReportedConfiguration .getMergedConfiguration().windowConfiguration.getRotation(); fillClientWindowFramesAndConfiguration(mClientWindowFrames, mLastReportedConfiguration, @@ -3919,7 +3936,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration, getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId, mSyncSeqId, resizeMode); - if (drawPending && prevRotation != mLastReportedConfiguration + if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration .getMergedConfiguration().windowConfiguration.getRotation()) { mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime(); ProtoLog.v(WM_DEBUG_ORIENTATION, @@ -4403,6 +4420,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.println(prefix + "Requested visibilities: " + visibilityString); } } + + pw.println(prefix + "mAlreadyRequestedSync=" + mAlreadyRequestedSync); } @Override @@ -5930,6 +5949,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mRedrawForSyncReported) { mClientWasDrawingForSync = true; } + mAlreadyRequestedSync = false; super.finishSync(outMergedTransaction, cancel); } @@ -6196,4 +6216,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @WindowTraceLogLevel int logLevel) { dumpDebug(proto, fieldId, logLevel); } + + public boolean cancelAndRedraw() { + return mSyncState != SYNC_STATE_NONE && mAlreadyRequestedSync; + } } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index ab72e49f1e4f..437c9344d793 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -448,8 +448,14 @@ class WindowToken extends WindowContainer<WindowState> { if (mFixedRotationTransformState != null) { mFixedRotationTransformState.disassociate(this); } + // TODO(b/233855302): Remove TaskFragment override if the DisplayContent uses the same + // bounds for screenLayout calculation. + final Configuration overrideConfig = new Configuration(config); + overrideConfig.screenLayout = TaskFragment.computeScreenLayoutOverride( + overrideConfig.screenLayout, overrideConfig.screenWidthDp, + overrideConfig.screenHeightDp); mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames, - new Configuration(config), mDisplayContent.getRotation()); + overrideConfig, mDisplayContent.getRotation()); mFixedRotationTransformState.mAssociatedTokens.add(this); mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames); onFixedRotationStatePrepared(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ef311c249c5f..66c9f55b0403 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -412,7 +412,7 @@ public final class SystemServer implements Dumpable { "/apex/com.android.uwb/javalib/service-uwb.jar"; private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService"; private static final String BLUETOOTH_APEX_SERVICE_JAR_PATH = - "/apex/com.android.bluetooth/javalib/service-bluetooth.jar"; + "/apex/com.android.btservices/javalib/service-bluetooth.jar"; private static final String BLUETOOTH_SERVICE_CLASS = "com.android.server.bluetooth.BluetoothService"; private static final String SAFETY_CENTER_SERVICE_CLASS = diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java index fa8d569d8e3c..f02571fe7cd1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java @@ -1141,6 +1141,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Long> longRunningFGSWindow = null; DeviceConfigSession<Long> longRunningFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; + DeviceConfigSession<Boolean> longRunningFGS = null; try { longRunningFGSMonitor = new DeviceConfigSession<>( @@ -1171,6 +1172,13 @@ public final class BackgroundRestrictionTest { ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); + longRunningFGS = new DeviceConfigSession<>( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING, + DeviceConfig::getBoolean, + ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING); + longRunningFGS.set(true); + // Basic case mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, true); @@ -1214,6 +1222,23 @@ public final class BackgroundRestrictionTest { testPid2, false); checkNotificationGone(testPkgName2, timeout(windowMs), notificationId); + // Turn OFF the notification. + longRunningFGS.set(false); + clearInvocations(mInjector.getNotificationManager()); + mBgRestrictionController.resetRestrictionSettings(); + // Start the FGS again. + mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, + testPid2, true); + // Verify we do NOT have the notification. + checkNotificationShown( + new String[] {testPkgName2}, timeout(windowMs * 2).times(0), false); + // Stop this FGS + mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, + testPid2, false); + + // Turn it back ON. + longRunningFGS.set(true); + // Start over with concurrent cases. clearInvocations(mInjector.getNotificationManager()); mBgRestrictionController.resetRestrictionSettings(); @@ -1306,6 +1331,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(longRunningFGSWindow); closeIfNotNull(longRunningFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); + closeIfNotNull(longRunningFGS); } } @@ -1332,6 +1358,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Long> mediaPlaybackFGSThreshold = null; DeviceConfigSession<Long> locationFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; + DeviceConfigSession<Boolean> longRunningFGS = null; doReturn(testPkgName1).when(mInjector).getPackageName(testPid1); doReturn(testPkgName2).when(mInjector).getPackageName(testPid2); @@ -1379,6 +1406,13 @@ public final class BackgroundRestrictionTest { ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); + longRunningFGS = new DeviceConfigSession<>( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING, + DeviceConfig::getBoolean, + ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING); + longRunningFGS.set(true); + // Long-running FGS with type "location", but ran for a very short time. runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, FOREGROUND_SERVICE_TYPE_LOCATION, 0, null, OP_NONE, null, null, @@ -1487,6 +1521,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(mediaPlaybackFGSThreshold); closeIfNotNull(locationFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); + closeIfNotNull(longRunningFGS); } } diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java index fe3034dc569d..038cbc032375 100644 --- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java @@ -76,12 +76,15 @@ public final class DeviceStateManagerServiceTest { private TestDeviceStatePolicy mPolicy; private TestDeviceStateProvider mProvider; private DeviceStateManagerService mService; + private TestSystemPropertySetter mSysPropSetter; @Before public void setup() { mProvider = new TestDeviceStateProvider(); mPolicy = new TestDeviceStatePolicy(mProvider); - mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy); + mSysPropSetter = new TestSystemPropertySetter(); + mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy, + mSysPropSetter); // Necessary to allow us to check for top app process id in tests mService.mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class); @@ -107,6 +110,8 @@ public final class DeviceStateManagerServiceTest { public void baseStateChanged() { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -115,6 +120,8 @@ public final class DeviceStateManagerServiceTest { flushHandler(); assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE.getIdentifier()); @@ -128,6 +135,8 @@ public final class DeviceStateManagerServiceTest { flushHandler(); assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE.getIdentifier()); @@ -136,6 +145,8 @@ public final class DeviceStateManagerServiceTest { flushHandler(); assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE.getIdentifier()); @@ -157,6 +168,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -170,6 +183,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -182,6 +197,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE); @@ -193,6 +210,8 @@ public final class DeviceStateManagerServiceTest { // supported. assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE); @@ -211,6 +230,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE); @@ -223,6 +244,8 @@ public final class DeviceStateManagerServiceTest { // supported. assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE); @@ -315,6 +338,8 @@ public final class DeviceStateManagerServiceTest { TestDeviceStateManagerCallback.STATUS_ACTIVE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), @@ -333,6 +358,8 @@ public final class DeviceStateManagerServiceTest { TestDeviceStateManagerCallback.STATUS_CANCELED); // Committed state is set back to the requested state once the override is cleared. assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertFalse(mService.getOverrideState().isPresent()); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), @@ -385,9 +412,10 @@ public final class DeviceStateManagerServiceTest { // callback. assertEquals(callback.getLastNotifiedStatus(secondRequestToken), TestDeviceStateManagerCallback.STATUS_UNKNOWN); - assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.of(DEFAULT_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -397,6 +425,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -412,6 +442,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE.getIdentifier()); @@ -458,6 +490,8 @@ public final class DeviceStateManagerServiceTest { // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE.getIdentifier()); @@ -471,6 +505,8 @@ public final class DeviceStateManagerServiceTest { // Committed state is set back to the requested state once the override is cleared. assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertFalse(mService.getOverrideState().isPresent()); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE.getIdentifier()); @@ -495,6 +531,8 @@ public final class DeviceStateManagerServiceTest { TestDeviceStateManagerCallback.STATUS_ACTIVE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), @@ -509,6 +547,8 @@ public final class DeviceStateManagerServiceTest { // Committed state is set back to the requested state as the override state is no longer // supported. assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); + assertEquals(mSysPropSetter.getValue(), + DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); assertFalse(mService.getOverrideState().isPresent()); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), @@ -673,4 +713,18 @@ public final class DeviceStateManagerServiceTest { return mLastNotifiedStatus.getOrDefault(requestToken, STATUS_UNKNOWN); } } + + private static final class TestSystemPropertySetter implements + DeviceStateManagerService.SystemPropertySetter { + private String mValue; + + @Override + public void setDebugTracingDeviceStateProperty(String value) { + mValue = value; + } + + public String getValue() { + return mValue; + } + } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java index c735bb7add0a..8a96febcd1e9 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -778,8 +778,7 @@ public class VibratorManagerServiceTest { assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); - vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), - HAPTIC_FEEDBACK_ATTRS); + vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), HAPTIC_FEEDBACK_ATTRS); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1, @@ -793,49 +792,78 @@ public class VibratorManagerServiceTest { } @Test - public void vibrate_withOngoingAlarmVibration_ignoresEffect() throws Exception { + public void vibrate_withNewRepeatingVibration_cancelsOngoingEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); VibrationEffect alarmEffect = VibrationEffect.createWaveform( new long[]{10_000, 10_000}, new int[]{128, 255}, -1); - vibrate(service, alarmEffect, new VibrationAttributes.Builder().setUsage( - VibrationAttributes.USAGE_ALARM).build()); + vibrate(service, alarmEffect, ALARM_ATTRS); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); - vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), - HAPTIC_FEEDBACK_ATTRS); + VibrationEffect repeatingEffect = VibrationEffect.createWaveform( + new long[]{10_000, 10_000}, new int[]{128, 255}, 1); + vibrate(service, repeatingEffect, NOTIFICATION_ATTRS); - // Wait before checking it never played a second effect. - assertFalse(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1, - service, /* timeout= */ 50)); + // VibrationThread will start this vibration async, so wait before checking it started. + assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1, + service, TEST_TIMEOUT_MILLIS)); + + // The second vibration should have recorded that the vibrators were turned on. + verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); } @Test - public void vibrate_withOngoingRingtoneVibration_ignoresEffect() throws Exception { + public void vibrate_withOngoingHigherImportanceVibration_ignoresEffect() throws Exception { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorManagerService service = createSystemReadyService(); - VibrationEffect alarmEffect = VibrationEffect.createWaveform( + VibrationEffect effect = VibrationEffect.createWaveform( new long[]{10_000, 10_000}, new int[]{128, 255}, -1); - vibrate(service, alarmEffect, new VibrationAttributes.Builder().setUsage( - VibrationAttributes.USAGE_RINGTONE).build()); + vibrate(service, effect, ALARM_ATTRS); // VibrationThread will start this vibration async, so wait before checking it started. assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), service, TEST_TIMEOUT_MILLIS)); - vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), - HAPTIC_FEEDBACK_ATTRS); + vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS); // Wait before checking it never played a second effect. assertFalse(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1, service, /* timeout= */ 50)); + + // The second vibration shouldn't have recorded that the vibrators were turned on. + verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong()); + } + + @Test + public void vibrate_withOngoingLowerImportanceVibration_cancelsOngoingEffect() + throws Exception { + mockVibrators(1); + mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + VibratorManagerService service = createSystemReadyService(); + + VibrationEffect effect = VibrationEffect.createWaveform( + new long[]{10_000, 10_000}, new int[]{128, 255}, -1); + vibrate(service, effect, HAPTIC_FEEDBACK_ATTRS); + + // VibrationThread will start this vibration async, so wait before checking it started. + assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(), + service, TEST_TIMEOUT_MILLIS)); + + vibrate(service, effect, RINGTONE_ATTRS); + + // VibrationThread will start this vibration async, so wait before checking it started. + assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 1, + service, TEST_TIMEOUT_MILLIS)); + + // The second vibration should have recorded that the vibrators were turned on. + verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong()); } @Test @@ -1052,15 +1080,15 @@ public class VibratorManagerServiceTest { IVibrator.CAP_COMPOSE_EFFECTS); VibratorManagerService service = createSystemReadyService(); - vibrate(service, CombinedVibration.startSequential() - .addNext(1, VibrationEffect.createOneShot(100, 125)) - .combine(), NOTIFICATION_ATTRS); - assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1, - service, TEST_TIMEOUT_MILLIS)); - vibrate(service, VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f) .compose(), HAPTIC_FEEDBACK_ATTRS); + assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1, + service, TEST_TIMEOUT_MILLIS)); + + vibrate(service, CombinedVibration.startSequential() + .addNext(1, VibrationEffect.createOneShot(100, 125)) + .combine(), NOTIFICATION_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 2, service, TEST_TIMEOUT_MILLIS)); @@ -1070,25 +1098,25 @@ public class VibratorManagerServiceTest { assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 3, service, TEST_TIMEOUT_MILLIS)); + // Ring vibrations have intensity OFF and are not played. vibrate(service, VibrationEffect.createOneShot(100, 125), RINGTONE_ATTRS); assertFalse(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() > 3, - service, TEST_TIMEOUT_MILLIS)); + service, /* timeout= */ 50)); + // Only 3 effects played successfully. assertEquals(3, fakeVibrator.getAllEffectSegments().size()); + // Haptic feedback vibrations will be scaled with SCALE_LOW or none if default is low. + assertEquals(defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW, + 0.5 > ((PrimitiveSegment) fakeVibrator.getAllEffectSegments().get(0)).getScale()); + // Notification vibrations will be scaled with SCALE_HIGH or none if default is high. assertEquals(defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH, 0.6 < fakeVibrator.getAmplitudes().get(0)); - // Haptic feedback vibrations will be scaled with SCALE_LOW or none if default is low. - assertEquals(defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW, - 0.5 > ((PrimitiveSegment) fakeVibrator.getAllEffectSegments().get(1)).getScale()); - // Alarm vibration will be scaled with SCALE_NONE. assertEquals(1f, ((PrimitiveSegment) fakeVibrator.getAllEffectSegments().get(2)).getScale(), 1e-5); - - // Ring vibrations have intensity OFF and are not played. } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 2477f6c41d4f..cfeaf850da03 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1996,7 +1996,8 @@ public class ActivityRecordTests extends WindowTestsBase { any() /* window */, any() /* attrs */, anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* requestedVisibilities */, any() /* outInputChannel */, - any() /* outInsetsState */, any() /* outActiveControls */); + any() /* outInsetsState */, any() /* outActiveControls */, + any() /* outAttachedFrame */); mAtm.mWindowManager.mStartingSurfaceController .createTaskSnapshotSurface(activity, snapshot); } catch (RemoteException ignored) { diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index 2c1c38f3bee8..fc41a94d3355 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -181,7 +181,8 @@ public class BackNavigationControllerTests extends WindowTestsBase { Task task = createTopTaskWithActivity(); WindowState appWindow = task.getTopVisibleAppMainWindow(); - WindowOnBackInvokedDispatcher dispatcher = new WindowOnBackInvokedDispatcher(); + WindowOnBackInvokedDispatcher dispatcher = + new WindowOnBackInvokedDispatcher(true /* applicationCallbackEnabled */); doAnswer(invocation -> { appWindow.setOnBackInvokedCallbackInfo(invocation.getArgument(1)); return null; diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index a19b19ec6af9..d737963f80e7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -78,10 +78,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; -import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_TOKEN_TRANSFORM; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; -import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; @@ -2426,7 +2424,7 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testImeMenuDialogFocusWhenImeLayeringTargetChanges() { final WindowState imeMenuDialog = - createWindow(mImeWindow, TYPE_INPUT_METHOD_DIALOG, "imeMenuDialog"); + createWindow(null, TYPE_INPUT_METHOD_DIALOG, "imeMenuDialog"); makeWindowVisibleAndDrawn(imeMenuDialog, mImeWindow); assertTrue(imeMenuDialog.canReceiveKeys()); mDisplayContent.setInputMethodWindowLocked(mImeWindow); @@ -2439,13 +2437,11 @@ public class DisplayContentTests extends WindowTestsBase { doReturn(true).when(imeAppTarget).getRequestedVisibility(ITYPE_IME); assertEquals(imeMenuDialog, mDisplayContent.findFocusedWindow()); - // Verify imeMenuDialog doesn't be focused window if the next IME target does not - // request IME visible. + // Verify imeMenuDialog doesn't be focused window if the next IME target is closing. final WindowState nextImeAppTarget = createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "nextImeAppTarget"); - spyOn(nextImeAppTarget); - doReturn(true).when(nextImeAppTarget).isAnimating(PARENTS | TRANSITION, - ANIMATION_TYPE_APP_TRANSITION); + makeWindowVisibleAndDrawn(nextImeAppTarget); + nextImeAppTarget.mActivityRecord.commitVisibility(false, false); mDisplayContent.setImeLayeringTarget(nextImeAppTarget); assertNotEquals(imeMenuDialog, mDisplayContent.findFocusedWindow()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java index db3a51ca4791..2956c14155b9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java @@ -39,7 +39,6 @@ import static com.android.server.wm.SizeCompatTests.rotateDisplay; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -211,10 +210,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { assertThat(activityConfigBounds.width()).isEqualTo(activityBounds.width()); assertThat(activityConfigBounds.height()).isEqualTo(activityBounds.height()); assertThat(activitySizeCompatBounds.height()).isEqualTo(newTaskBounds.height()); - final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration - .getDefaultMinAspectRatioForUnresizableApps(); - assertEquals(activitySizeCompatBounds.width(), - newTaskBounds.height() / defaultAspectRatio, 0.5); + assertThat(activitySizeCompatBounds.width()).isEqualTo( + newTaskBounds.height() * newTaskBounds.height() / newTaskBounds.width()); } @Test @@ -234,9 +231,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { assertThat(mFirstActivity.inSizeCompatMode()).isFalse(); assertThat(taskBounds).isEqualTo(dagBounds); assertThat(activityBounds.width()).isEqualTo(dagBounds.width()); - final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration - .getDefaultMinAspectRatioForUnresizableApps(); - assertEquals(activityBounds.height(), dagBounds.width() / defaultAspectRatio, 0.5); + assertThat(activityBounds.height()) + .isEqualTo(dagBounds.width() * dagBounds.width() / dagBounds.height()); } @Test 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 7f70882a70fc..324e244c46f5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -1471,6 +1471,8 @@ public class SizeCompatTests extends WindowTestsBase { final float fixedOrientationLetterboxAspectRatio = 1.1f; mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio( fixedOrientationLetterboxAspectRatio); + mActivity.mWmService.mLetterboxConfiguration.setDefaultMinAspectRatioForUnresizableApps( + 1.5f); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds()); @@ -1496,7 +1498,9 @@ public class SizeCompatTests extends WindowTestsBase { @Test public void testSplitAspectRatioForUnresizablePortraitApps() { // Set up a display in landscape and ignoring orientation request. - setUpDisplaySizeWithApp(1600, 1400); + int screenWidth = 1600; + int screenHeight = 1400; + setUpDisplaySizeWithApp(screenWidth, screenHeight); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.mWmService.mLetterboxConfiguration .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true); @@ -1520,6 +1524,7 @@ public class SizeCompatTests extends WindowTestsBase { new TestSplitOrganizer(mAtm, mActivity.getDisplayContent()); // Move activity to split screen which takes half of the screen. mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test"); + organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(screenWidth), screenHeight); assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode()); assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode()); // Checking that there is no size compat mode. @@ -1528,8 +1533,10 @@ public class SizeCompatTests extends WindowTestsBase { @Test public void testSplitAspectRatioForUnresizableLandscapeApps() { - // Set up a display in landscape and ignoring orientation request. - setUpDisplaySizeWithApp(1400, 1600); + // Set up a display in portrait and ignoring orientation request. + int screenWidth = 1400; + int screenHeight = 1600; + setUpDisplaySizeWithApp(screenWidth, screenHeight); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.mWmService.mLetterboxConfiguration .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true); @@ -1553,6 +1560,7 @@ public class SizeCompatTests extends WindowTestsBase { new TestSplitOrganizer(mAtm, mActivity.getDisplayContent()); // Move activity to split screen which takes half of the screen. mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test"); + organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight)); assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode()); assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode()); // Checking that there is no size compat mode. @@ -2071,12 +2079,7 @@ public class SizeCompatTests extends WindowTestsBase { // Activity bounds fill split screen. final Rect primarySplitBounds = new Rect(organizer.mPrimary.getBounds()); final Rect letterboxedBounds = new Rect(mActivity.getBounds()); - // Activity is letterboxed for aspect ratio. - assertEquals(primarySplitBounds.height(), letterboxedBounds.height()); - final float defaultAspectRatio = mActivity.mWmService.mLetterboxConfiguration - .getDefaultMinAspectRatioForUnresizableApps(); - assertEquals(primarySplitBounds.height() / defaultAspectRatio, - letterboxedBounds.width(), 0.5); + assertEquals(primarySplitBounds, letterboxedBounds); } @Test @@ -2618,6 +2621,16 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(newDensity, mActivity.getConfiguration().densityDpi); } + private int getExpectedSplitSize(int dimensionToSplit) { + int dividerWindowWidth = + mActivity.mWmService.mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_thickness); + int dividerInsets = + mActivity.mWmService.mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_insets); + return (dimensionToSplit - (dividerWindowWidth - dividerInsets * 2)) / 2; + } + private void assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity( float letterboxHorizontalPositionMultiplier) { // Set up a display in landscape and ignoring orientation request. diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java index ea18e58fe999..739e783e7c1b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java @@ -72,7 +72,7 @@ public class WindowLayoutTests { private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0); private final WindowLayout mWindowLayout = new WindowLayout(); - private final ClientWindowFrames mOutFrames = new ClientWindowFrames(); + private final ClientWindowFrames mFrames = new ClientWindowFrames(); private WindowManager.LayoutParams mAttrs; private InsetsState mState; @@ -82,7 +82,6 @@ public class WindowLayoutTests { private int mRequestedWidth; private int mRequestedHeight; private InsetsVisibilities mRequestedVisibilities; - private Rect mAttachedWindowFrame; private float mCompatScale; @Before @@ -100,14 +99,14 @@ public class WindowLayoutTests { mRequestedWidth = DISPLAY_WIDTH; mRequestedHeight = DISPLAY_HEIGHT; mRequestedVisibilities = new InsetsVisibilities(); - mAttachedWindowFrame = null; mCompatScale = 1f; + mFrames.attachedFrame = null; } private void computeFrames() { mWindowLayout.computeFrames(mAttrs, mState, mDisplayCutoutSafe, mWindowBounds, mWindowingMode, mRequestedWidth, mRequestedHeight, mRequestedVisibilities, - mAttachedWindowFrame, mCompatScale, mOutFrames); + mCompatScale, mFrames); } private void addDisplayCutout() { @@ -145,9 +144,9 @@ public class WindowLayoutTests { public void defaultParams() { computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.frame); } @Test @@ -156,9 +155,9 @@ public class WindowLayoutTests { mRequestedHeight = UNSPECIFIED_LENGTH; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.frame); } @Test @@ -172,9 +171,9 @@ public class WindowLayoutTests { mAttrs.gravity = Gravity.LEFT | Gravity.TOP; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mFrames.frame); } @Test @@ -186,11 +185,24 @@ public class WindowLayoutTests { computeFrames(); assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, - mOutFrames.displayFrame); + mFrames.displayFrame); assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, - mOutFrames.parentFrame); + mFrames.parentFrame); assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, - mOutFrames.frame); + mFrames.frame); + } + + @Test + public void attachedFrame() { + final int bottom = (DISPLAY_HEIGHT - STATUS_BAR_HEIGHT - NAVIGATION_BAR_HEIGHT) / 2; + mFrames.attachedFrame = new Rect(0, STATUS_BAR_HEIGHT, DISPLAY_WIDTH, bottom); + mRequestedWidth = UNSPECIFIED_LENGTH; + mRequestedHeight = UNSPECIFIED_LENGTH; + computeFrames(); + + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertEquals(mFrames.attachedFrame, mFrames.parentFrame); + assertEquals(mFrames.attachedFrame, mFrames.frame); } @Test @@ -198,9 +210,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(WindowInsets.Type.statusBars()); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.frame); } @Test @@ -208,9 +220,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(WindowInsets.Type.navigationBars()); computeFrames(); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrames.frame); } @Test @@ -218,9 +230,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(0, 0, mOutFrames.frame); + assertInsetByTopBottom(0, 0, mFrames.displayFrame); + assertInsetByTopBottom(0, 0, mFrames.parentFrame); + assertInsetByTopBottom(0, 0, mFrames.frame); } @Test @@ -228,9 +240,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(WindowInsets.Side.all()); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.frame); } @Test @@ -238,9 +250,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(WindowInsets.Side.TOP); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrames.frame); } @Test @@ -248,9 +260,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsSides(0); computeFrames(); - assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(0, 0, mOutFrames.frame); + assertInsetByTopBottom(0, 0, mFrames.displayFrame); + assertInsetByTopBottom(0, 0, mFrames.parentFrame); + assertInsetByTopBottom(0, 0, mFrames.frame); } @Test @@ -259,9 +271,9 @@ public class WindowLayoutTests { mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false); computeFrames(); - assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(0, 0, mOutFrames.frame); + assertInsetByTopBottom(0, 0, mFrames.displayFrame); + assertInsetByTopBottom(0, 0, mFrames.parentFrame); + assertInsetByTopBottom(0, 0, mFrames.frame); } @Test @@ -271,9 +283,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsIgnoringVisibility(true); computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.frame); } @Test @@ -284,9 +296,9 @@ public class WindowLayoutTests { mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; computeFrames(); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.parentFrame); - assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.frame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrames.displayFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mFrames.parentFrame); + assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mFrames.frame); } @Test @@ -297,11 +309,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.displayFrame); + mFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.parentFrame); + mFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.frame); + mFrames.frame); } @Test @@ -312,11 +324,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.displayFrame); + mFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.parentFrame); + mFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.frame); + mFrames.frame); } @Test @@ -327,9 +339,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.displayFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.parentFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.frame); } @Test @@ -344,9 +356,9 @@ public class WindowLayoutTests { mAttrs.privateFlags |= PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; computeFrames(); - assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.displayFrame); - assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.parentFrame); - assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mOutFrames.frame); + assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mFrames.displayFrame); + assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mFrames.parentFrame); + assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mFrames.frame); } @Test @@ -359,11 +371,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.displayFrame); + mFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.parentFrame); + mFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.frame); + mFrames.frame); } @Test @@ -373,9 +385,9 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame); - assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.displayFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.parentFrame); + assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrames.frame); } @Test @@ -386,11 +398,11 @@ public class WindowLayoutTests { computeFrames(); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.displayFrame); + mFrames.displayFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.parentFrame); + mFrames.parentFrame); assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0, - mOutFrames.frame); + mFrames.frame); } @Test @@ -400,8 +412,8 @@ public class WindowLayoutTests { mAttrs.setFitInsetsTypes(0); computeFrames(); - assertInsetByTopBottom(0, 0, mOutFrames.displayFrame); - assertInsetByTopBottom(0, 0, mOutFrames.parentFrame); - assertInsetByTopBottom(0, 0, mOutFrames.frame); + assertInsetByTopBottom(0, 0, mFrames.displayFrame); + assertInsetByTopBottom(0, 0, mFrames.parentFrame); + assertInsetByTopBottom(0, 0, mFrames.frame); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java index a0c20c2c6b68..e09a94f3bcf9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -49,6 +49,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.pm.PackageManager; +import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; @@ -281,7 +282,7 @@ public class WindowManagerServiceTests extends WindowTestsBase { mWm.addWindow(session, new TestIWindow(), params, View.VISIBLE, DEFAULT_DISPLAY, UserHandle.USER_SYSTEM, new InsetsVisibilities(), null, new InsetsState(), - new InsetsSourceControl[0]); + new InsetsSourceControl[0], new Rect()); verify(mWm.mWindowContextListenerController, never()).registerWindowContainerListener(any(), any(), anyInt(), anyInt(), any()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index c1ab823874c5..fb7400bc83ef 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -935,6 +935,15 @@ public class WindowStateTests extends WindowTestsBase { assertTrue(app.isReadyToDispatchInsetsState()); mDisplayContent.getInsetsStateController().notifyInsetsChanged(); verify(app).notifyInsetsChanged(); + + // Verify that invisible non-activity window won't dispatch insets changed. + final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay"); + makeWindowVisible(overlay); + assertTrue(overlay.isReadyToDispatchInsetsState()); + overlay.mHasSurface = false; + assertFalse(overlay.isReadyToDispatchInsetsState()); + mDisplayContent.getInsetsStateController().notifyInsetsChanged(); + assertFalse(overlay.getWindowFrames().hasInsetsChanged()); } @UseTestDisplay(addWindows = {W_INPUT_METHOD, W_ACTIVITY}) diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 434663bd8167..25db81fa2667 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -31,11 +31,18 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERV import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__APP_REQUEST_UPDATE_STATE; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_DETECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_REJECTED; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__ON_DISCONNECTED; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__START_EXTERNAL_SOURCE_DETECTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__START_SOFTWARE_DETECTION; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED; @@ -146,6 +153,13 @@ final class HotwordDetectionConnection { private static final int METRICS_KEYPHRASE_TRIGGERED_REJECT_UNEXPECTED_CALLBACK = HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECT_UNEXPECTED_CALLBACK; + private static final int METRICS_EXTERNAL_SOURCE_DETECTED = + HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_DETECTED; + private static final int METRICS_EXTERNAL_SOURCE_REJECTED = + HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_REJECTED; + private static final int METRICS_EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION = + HOTWORD_DETECTOR_EVENTS__EVENT__EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION; + private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool(); // TODO: This may need to be a Handler(looper) private final ScheduledExecutorService mScheduledExecutorService = @@ -382,6 +396,10 @@ final class HotwordDetectionConnection { } void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__APP_REQUEST_UPDATE_STATE, + mVoiceInteractionServiceUid); + // Prevent doing the init late, so restart is handled equally to a clean process start. // TODO(b/191742511): this logic needs a test if (!mUpdateStateAfterStartFinished.get() @@ -422,14 +440,23 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onDetected"); } synchronized (mLock) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED); if (!mPerformingSoftwareHotwordDetection) { Slog.i(TAG, "Hotword detection has already completed"); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK); return; } mPerformingSoftwareHotwordDetection = false; try { enforcePermissionsForDataDelivery(); } catch (SecurityException e) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); mSoftwareCallback.onError(); return; } @@ -449,6 +476,9 @@ final class HotwordDetectionConnection { if (DEBUG) { Slog.wtf(TAG, "onRejected"); } + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED); // onRejected isn't allowed here, and we are not expecting it. } }; @@ -460,6 +490,9 @@ final class HotwordDetectionConnection { null, null, internalCallback)); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__START_SOFTWARE_DETECTION, + mVoiceInteractionServiceUid); } public void startListeningFromExternalSource( @@ -891,6 +924,9 @@ final class HotwordDetectionConnection { @Override public void onRejected(HotwordRejectedResult result) throws RemoteException { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + METRICS_EXTERNAL_SOURCE_REJECTED, + mVoiceInteractionServiceUid); mScheduledExecutorService.schedule( () -> { bestEffortClose(serviceAudioSink, audioSource); @@ -912,6 +948,9 @@ final class HotwordDetectionConnection { @Override public void onDetected(HotwordDetectedResult triggerResult) throws RemoteException { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + METRICS_EXTERNAL_SOURCE_DETECTED, + mVoiceInteractionServiceUid); mScheduledExecutorService.schedule( () -> { bestEffortClose(serviceAudioSink, audioSource); @@ -922,6 +961,9 @@ final class HotwordDetectionConnection { try { enforcePermissionsForDataDelivery(); } catch (SecurityException e) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + METRICS_EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION, + mVoiceInteractionServiceUid); callback.onError(); return; } @@ -942,6 +984,9 @@ final class HotwordDetectionConnection { // A copy of this has been created and passed to the hotword validator bestEffortClose(serviceAudioSource); }); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__START_EXTERNAL_SOURCE_DETECTION, + mVoiceInteractionServiceUid); } private class ServiceConnectionFactory { @@ -1002,7 +1047,12 @@ final class HotwordDetectionConnection { return; } mIsBound = connected; - if (connected && !mIsLoggedFirstConnect) { + + if (!connected) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__ON_DISCONNECTED, + mVoiceInteractionServiceUid); + } else if (!mIsLoggedFirstConnect) { mIsLoggedFirstConnect = true; HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED, |