diff options
Diffstat (limited to 'libs')
184 files changed, 3197 insertions, 1571 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java index 3ff531573f1f..0dba6b0049c0 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java @@ -72,6 +72,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { @NonNull Configuration parentConfig); void onActivityReparentToTask(int taskId, @NonNull Intent activityIntent, @NonNull IBinder activityToken); + void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType); } /** @@ -323,4 +324,18 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { mCallback.onActivityReparentToTask(taskId, activityIntent, activityToken); } } + + @Override + public void onTaskFragmentError(@NonNull IBinder errorCallbackToken, + @Nullable TaskFragmentInfo taskFragmentInfo, + int opType, @NonNull Throwable exception) { + if (taskFragmentInfo != null) { + final IBinder fragmentToken = taskFragmentInfo.getFragmentToken(); + mFragmentInfos.put(fragmentToken, taskFragmentInfo); + } + + if (mCallback != null) { + mCallback.onTaskFragmentError(taskFragmentInfo, opType); + } + } } 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 2f79caeec7ba..c688080ad929 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -16,8 +16,11 @@ package androidx.window.extensions.embedding; +import static android.app.ActivityManager.START_SUCCESS; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT; +import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; import static androidx.window.extensions.embedding.SplitContainer.getFinishPrimaryWithSecondaryBehavior; import static androidx.window.extensions.embedding.SplitContainer.getFinishSecondaryWithPrimaryBehavior; @@ -97,6 +100,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>(); private final Handler mHandler; private final Object mLock = new Object(); + private final ActivityStartMonitor mActivityStartMonitor; public SplitController() { final MainThreadExecutor executor = new MainThreadExecutor(); @@ -108,7 +112,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen new LifecycleCallbacks()); // Intercept activity starts to route activities to new containers if necessary. Instrumentation instrumentation = activityThread.getInstrumentation(); - instrumentation.addMonitor(new ActivityStartMonitor()); + mActivityStartMonitor = new ActivityStartMonitor(); + instrumentation.addMonitor(mActivityStartMonitor); } /** Updates the embedding rules applied to future activity launches. */ @@ -293,6 +298,37 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } + @Override + public void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType) { + synchronized (mLock) { + switch (opType) { + case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: + case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: { + final TaskFragmentContainer container; + if (taskFragmentInfo != null) { + container = getContainer(taskFragmentInfo.getFragmentToken()); + } else { + container = null; + } + if (container == null) { + break; + } + + // Update the latest taskFragmentInfo and perform necessary clean-up + container.setInfo(taskFragmentInfo); + container.clearPendingAppearedActivities(); + if (container.isEmpty()) { + mPresenter.cleanupContainer(container, false /* shouldFinishDependent */); + } + break; + } + default: + Log.e(TAG, "onTaskFragmentError: taskFragmentInfo = " + taskFragmentInfo + + ", opType = " + opType); + } + } + } + /** Called on receiving {@link #onTaskFragmentVanished(TaskFragmentInfo)} for cleanup. */ private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) { for (int i = mTaskContainers.size() - 1; i >= 0; i--) { @@ -1385,6 +1421,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return ActivityThread.currentActivityThread().getActivity(activityToken); } + @VisibleForTesting + ActivityStartMonitor getActivityStartMonitor() { + return mActivityStartMonitor; + } + /** * Gets the token of the initial TaskFragment that embedded this activity. Do not rely on it * after creation because the activity could be reparented. @@ -1536,7 +1577,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * A monitor that intercepts all activity start requests originating in the client process and * can amend them to target a specific task fragment to form a split. */ - private class ActivityStartMonitor extends Instrumentation.ActivityMonitor { + @VisibleForTesting + class ActivityStartMonitor extends Instrumentation.ActivityMonitor { + @VisibleForTesting + Intent mCurrentIntent; @Override public Instrumentation.ActivityResult onStartActivity(@NonNull Context who, @@ -1564,11 +1608,29 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // the dedicated container. options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, launchedInTaskFragment.getTaskFragmentToken()); + mCurrentIntent = intent; } } return super.onStartActivity(who, intent, options); } + + @Override + public void onStartActivityResult(int result, @NonNull Bundle bOptions) { + super.onStartActivityResult(result, bOptions); + if (mCurrentIntent != null && result != START_SUCCESS) { + // Clear the pending appeared intent if the activity was not started successfully. + final IBinder token = bOptions.getBinder( + ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN); + if (token != null) { + final TaskFragmentContainer container = getContainer(token); + if (container != null) { + container.clearPendingAppearedIntentIfNeeded(mCurrentIntent); + } + } + } + mCurrentIntent = null; + } } /** diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java index abf32a26efa2..37f5b6dc399e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -193,11 +193,32 @@ class TaskFragmentContainer { mPendingAppearedActivities.remove(pendingAppearedActivity); } + void clearPendingAppearedActivities() { + mPendingAppearedActivities.clear(); + mPendingAppearedIntent = null; + } + @Nullable Intent getPendingAppearedIntent() { return mPendingAppearedIntent; } + void setPendingAppearedIntent(@Nullable Intent intent) { + mPendingAppearedIntent = intent; + } + + /** + * Clears the pending appeared Intent if it is the same as given Intent. Otherwise, the + * pending appeared Intent is cleared when TaskFragmentInfo is set and is not empty (has + * running activities). + */ + void clearPendingAppearedIntentIfNeeded(@NonNull Intent intent) { + if (mPendingAppearedIntent == null || mPendingAppearedIntent != intent) { + return; + } + mPendingAppearedIntent = null; + } + boolean hasActivity(@NonNull IBinder token) { if (mInfo != null && mInfo.getActivities().contains(token)) { return true; @@ -230,13 +251,18 @@ class TaskFragmentContainer { void setInfo(@NonNull TaskFragmentInfo info) { if (!mIsFinished && mInfo == null && info.isEmpty()) { - // onTaskFragmentAppeared with empty info. We will remove the TaskFragment if it is - // still empty after timeout. + // onTaskFragmentAppeared with empty info. We will remove the TaskFragment if no + // pending appeared intent/activities. Otherwise, wait and removing the TaskFragment if + // it is still empty after timeout. mAppearEmptyTimeout = () -> { mAppearEmptyTimeout = null; mController.onTaskFragmentAppearEmptyTimeout(this); }; - mController.getHandler().postDelayed(mAppearEmptyTimeout, APPEAR_EMPTY_TIMEOUT_MS); + if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) { + mController.getHandler().postDelayed(mAppearEmptyTimeout, APPEAR_EMPTY_TIMEOUT_MS); + } else { + mAppearEmptyTimeout.run(); + } } else if (mAppearEmptyTimeout != null && !info.isEmpty()) { mController.getHandler().removeCallbacks(mAppearEmptyTimeout); mAppearEmptyTimeout = null; 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 18086f552ea3..6bfb16a3c22d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -25,8 +25,7 @@ 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.ActivityClient; import android.app.Application; import android.app.WindowConfiguration; import android.content.Context; @@ -34,7 +33,6 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; import android.util.ArrayMap; -import android.util.Log; import androidx.annotation.NonNull; import androidx.window.common.CommonFoldingFeature; @@ -179,57 +177,49 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private List<DisplayFeature> getDisplayFeatures( @NonNull Activity activity, List<CommonFoldingFeature> storedFeatures) { List<DisplayFeature> features = new ArrayList<>(); - int displayId = activity.getDisplay().getDisplayId(); - if (displayId != DEFAULT_DISPLAY) { - Log.w(TAG, "This sample doesn't support display features on secondary displays"); + if (!shouldReportDisplayFeatures(activity)) { return features; - } 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; - } else { - for (CommonFoldingFeature baseFeature : storedFeatures) { - Integer state = convertToExtensionState(baseFeature.getState()); - if (state == null) { - continue; - } - Rect featureRect = baseFeature.getRect(); - rotateRectToDisplayRotation(displayId, featureRect); - transformToWindowSpaceRect(activity, featureRect); + } - if (!isRectZero(featureRect)) { - // TODO(b/228641877) Remove guarding if when fixed. - features.add(new FoldingFeature(featureRect, baseFeature.getType(), state)); - } + int displayId = activity.getDisplay().getDisplayId(); + for (CommonFoldingFeature baseFeature : storedFeatures) { + Integer state = convertToExtensionState(baseFeature.getState()); + if (state == null) { + continue; + } + Rect featureRect = baseFeature.getRect(); + rotateRectToDisplayRotation(displayId, featureRect); + transformToWindowSpaceRect(activity, featureRect); + + if (!isRectZero(featureRect)) { + // TODO(b/228641877): Remove guarding when fixed. + features.add(new FoldingFeature(featureRect, baseFeature.getType(), state)); } - return features; } + return features; } /** - * Checks whether the task associated with the activity is in multi-window. If task info is not - * available it defaults to {@code true}. + * Checks whether display features should be reported for the activity. + * TODO(b/238948678): Support reporting display features in all windowing modes. */ - 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; - } + private boolean shouldReportDisplayFeatures(@NonNull Activity activity) { + int displayId = activity.getDisplay().getDisplayId(); + if (displayId != DEFAULT_DISPLAY) { + // Display features are not supported on secondary displays. + return false; } - if (task == null) { - // The task might be removed on the server already. - return true; + final int taskWindowingMode = ActivityClient.getInstance().getTaskWindowingMode( + activity.getActivityToken()); + if (taskWindowingMode == -1) { + // If we cannot determine the task windowing mode for any reason, it is likely that we + // won't be able to determine its position correctly as well. DisplayFeatures' bounds + // in this case can't be computed correctly, so we should skip. + return false; } - return WindowConfiguration.inMultiWindowMode(task.getTaskInfo().getWindowingMode()); + // 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 !WindowConfiguration.inMultiWindowMode(taskWindowingMode); } /** diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java index 042547fd30f2..4bc503369d0e 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java @@ -16,6 +16,7 @@ package androidx.window.extensions.embedding; +import static android.app.ActivityManager.START_CANCELED; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; @@ -293,6 +294,26 @@ public class SplitControllerTest { } @Test + public void testOnStartActivityResultError() { + final Intent intent = new Intent(); + final TaskContainer taskContainer = new TaskContainer(TASK_ID); + final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */, + intent, taskContainer, mSplitController); + final SplitController.ActivityStartMonitor monitor = + mSplitController.getActivityStartMonitor(); + + container.setPendingAppearedIntent(intent); + final Bundle bundle = new Bundle(); + bundle.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, + container.getTaskFragmentToken()); + monitor.mCurrentIntent = intent; + doReturn(container).when(mSplitController).getContainer(any()); + + monitor.onStartActivityResult(START_CANCELED, bundle); + assertNull(container.getPendingAppearedIntent()); + } + + @Test public void testOnActivityCreated() { mSplitController.onActivityCreated(mActivity); diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java index 28c2773e25cb..44c7e6c611de 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java @@ -209,21 +209,21 @@ public class TaskFragmentContainerTest { assertNull(container.mAppearEmptyTimeout); - // Not set if it is not appeared empty. - final TaskFragmentInfo info = mock(TaskFragmentInfo.class); - doReturn(new ArrayList<>()).when(info).getActivities(); - doReturn(false).when(info).isEmpty(); - container.setInfo(info); - - assertNull(container.mAppearEmptyTimeout); - // Set timeout if the first info set is empty. + final TaskFragmentInfo info = mock(TaskFragmentInfo.class); container.mInfo = null; doReturn(true).when(info).isEmpty(); container.setInfo(info); assertNotNull(container.mAppearEmptyTimeout); + // Not set if it is not appeared empty. + doReturn(new ArrayList<>()).when(info).getActivities(); + doReturn(false).when(info).isEmpty(); + container.setInfo(info); + + assertNull(container.mAppearEmptyTimeout); + // Remove timeout after the container becomes non-empty. doReturn(false).when(info).isEmpty(); container.setInfo(info); @@ -232,6 +232,7 @@ public class TaskFragmentContainerTest { // Running the timeout will call into SplitController.onTaskFragmentAppearEmptyTimeout. container.mInfo = null; + container.setPendingAppearedIntent(mIntent); doReturn(true).when(info).isEmpty(); container.setInfo(info); container.mAppearEmptyTimeout.run(); diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS index 780e4c1632f7..2c61df96eb03 100644 --- a/libs/WindowManager/OWNERS +++ b/libs/WindowManager/OWNERS @@ -1,6 +1,3 @@ set noparent include /services/core/java/com/android/server/wm/OWNERS - -# Give submodule owners in shell resource approval -per-file Shell/res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS new file mode 100644 index 000000000000..4b125904004a --- /dev/null +++ b/libs/WindowManager/Shell/OWNERS @@ -0,0 +1,4 @@ +xutan@google.com + +# Give submodule owners in shell resource approval +per-file res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index 6959a591338c..500ad5e5f977 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Instellings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gaan by verdeelde skerm in"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Kieslys"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string> <string name="pip_notification_message" msgid="8854051911700302620">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk moet gebruik nie, tik om instellings oop te maak en skakel dit af."</string> <string name="pip_play" msgid="3496151081459417097">"Speel"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Program sal dalk nie op \'n sekondêre skerm werk nie."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Program steun nie begin op sekondêre skerms nie."</string> <string name="accessibility_divider" msgid="703810061635792791">"Skermverdeler"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Volskerm links"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Links 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Links 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index fe22b2ce3278..2f4189dda164 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ቅንብሮች"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"የተከፈለ ማያ ገጽን አስገባ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ምናሌ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string> <string name="pip_play" msgid="3496151081459417097">"አጫውት"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"መተግበሪያ በሁለተኛ ማሳያ ላይ ላይሠራ ይችላል።"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"መተግበሪያ በሁለተኛ ማሳያዎች ላይ ማስጀመርን አይደግፍም።"</string> <string name="accessibility_divider" msgid="703810061635792791">"የተከፈለ የማያ ገጽ ከፋይ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"የግራ ሙሉ ማያ ገጽ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ግራ 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ግራ 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 2be6f39f9475..1f5fc9dc0301 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"الإعدادات"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"الدخول في وضع تقسيم الشاشة"</string> <string name="pip_menu_title" msgid="5393619322111827096">"القائمة"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string> <string name="pip_notification_message" msgid="8854051911700302620">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم أوقِف تفعيل هذه الميزة."</string> <string name="pip_play" msgid="3496151081459417097">"تشغيل"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"قد لا يعمل التطبيق على شاشة عرض ثانوية."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"لا يمكن تشغيل التطبيق على شاشات عرض ثانوية."</string> <string name="accessibility_divider" msgid="703810061635792791">"أداة تقسيم الشاشة"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"عرض النافذة اليسرى بملء الشاشة"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ضبط حجم النافذة اليسرى ليكون ٧٠%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ضبط حجم النافذة اليسرى ليكون ٥٠%"</string> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 098ee84de018..ca3542e59954 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ছেটিং"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"বিভাজিত স্ক্ৰীন ম’ডলৈ যাওক"</string> <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> চিত্ৰৰ ভিতৰৰ চিত্ৰত আছে"</string> <string name="pip_notification_message" msgid="8854051911700302620">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g> সুবিধাটো ব্যৱহাৰ কৰিব নোখোজে, তেন্তে ছেটিং খুলিবলৈ টিপক আৰু তালৈ গৈ ইয়াক অফ কৰক।"</string> <string name="pip_play" msgid="3496151081459417097">"প্লে কৰক"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"গৌণ ডিছপ্লেত এপে সঠিকভাৱে কাম নকৰিব পাৰে।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"গৌণ ডিছপ্লেত এপ্ লঞ্চ কৰিব নোৱাৰি।"</string> <string name="accessibility_divider" msgid="703810061635792791">"স্প্লিট স্ক্ৰীনৰ বিভাজক"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"বাওঁফালৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"বাওঁফালৰ স্ক্ৰীণখন ৭০% কৰক"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"বাওঁফালৰ স্ক্ৰীণখন ৫০% কৰক"</string> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 2f49ae6fdafc..25390bc57c96 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana daxil olun"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Şəkildə Şəkil Menyusu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> tətbiqinin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string> <string name="pip_play" msgid="3496151081459417097">"Oxudun"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Tətbiq ikinci ekranda işləməyə bilər."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Tətbiq ikinci ekranda başlamağı dəstəkləmir."</string> <string name="accessibility_divider" msgid="703810061635792791">"Bölünmüş ekran ayırıcısı"</string> + <string name="divider_title" msgid="5482989479865361192">"Bölünmüş ekran ayırıcısı"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Sol tam ekran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Sol 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Sol 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 0656fe185013..f4cb20ba8811 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Podešavanja"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Uđi na podeljeni ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da biste otvorili podešavanja i isključili je."</string> <string name="pip_play" msgid="3496151081459417097">"Pusti"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće funkcionisati na sekundarnom ekranu."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string> <string name="accessibility_divider" msgid="703810061635792791">"Razdelnik podeljenog ekrana"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Režim celog ekrana za levi ekran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Levi ekran 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Levi ekran 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 702f0abc07ae..f1b4ca539417 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Налады"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Падзяліць экран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць яе."</string> <string name="pip_play" msgid="3496151081459417097">"Прайграць"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Праграма можа не працаваць на дадатковых экранах."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Праграма не падтрымлівае запуск на дадатковых экранах."</string> <string name="accessibility_divider" msgid="703810061635792791">"Раздзяляльнік падзеленага экрана"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Левы экран – поўнаэкранны рэжым"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Левы экран – 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Левы экран – 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 0de16d37cd69..f7fbb3e794a4 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Преминаване към разделен екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string> <string name="pip_play" msgid="3496151081459417097">"Пускане"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Възможно е приложението да не работи на алтернативни дисплеи."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Приложението не поддържа използването на алтернативни дисплеи."</string> <string name="accessibility_divider" msgid="703810061635792791">"Разделител в режима за разделен екран"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ляв екран: Показване на цял екран"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Ляв екран: 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ляв екран: 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 9a48d186b231..0cb2f5e0c59e 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"সেটিংস"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"\'স্প্লিট স্ক্রিন\' মোড চালু করুন"</string> <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে ট্যাপ করে সেটিংসে গিয়ে সেটি বন্ধ করে দিন।"</string> <string name="pip_play" msgid="3496151081459417097">"চালান"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"সেকেন্ডারি ডিসপ্লেতে অ্যাপটি কাজ নাও করতে পারে।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"সেকেন্ডারি ডিসপ্লেতে অ্যাপ লঞ্চ করা যাবে না।"</string> <string name="accessibility_divider" msgid="703810061635792791">"বিভক্ত-স্ক্রিন বিভাজক"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"বাঁ দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"৭০% বাকি আছে"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"৫০% বাকি আছে"</string> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 31e906de7f51..c7086f14eaf9 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvori podijeljeni ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduciraj"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće raditi na sekundarnom ekranu."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string> <string name="accessibility_divider" msgid="703810061635792791">"Razdjelnik ekrana"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Lijevo cijeli ekran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Lijevo 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Lijevo 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index ca0a4211c435..1bb1d089be05 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Configuració"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entra al mode de pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string> <string name="pip_play" msgid="3496151081459417097">"Reprodueix"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"És possible que l\'aplicació no funcioni en una pantalla secundària."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'aplicació no es pot obrir en pantalles secundàries."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalles"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Pantalla esquerra completa"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Pantalla esquerra al 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Pantalla esquerra al 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index e8772fe269b6..def3f4f67605 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavení"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivovat rozdělenou obrazovku"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Nabídka"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string> <string name="pip_play" msgid="3496151081459417097">"Přehrát"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikace na sekundárním displeji nemusí fungovat."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikace nepodporuje spuštění na sekundárních displejích."</string> <string name="accessibility_divider" msgid="703810061635792791">"Čára rozdělující obrazovku"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Levá část na celou obrazovku"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70 % vlevo"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % vlevo"</string> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 2b55d4d688ac..6eedb83fcdd1 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Indstillinger"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Åbn opdelt skærm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string> <string name="pip_play" msgid="3496151081459417097">"Afspil"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen fungerer muligvis ikke på sekundære skærme."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan ikke åbnes på sekundære skærme."</string> <string name="accessibility_divider" msgid="703810061635792791">"Adskiller til opdelt skærm"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Vis venstre del i fuld skærm"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Venstre 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Venstre 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 03eee024f3be..fce0bd4c51cc 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Geteilter Bildschirm“ aktivieren"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string> <string name="pip_play" msgid="3496151081459417097">"Wiedergeben"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string> <string name="accessibility_divider" msgid="703810061635792791">"Bildschirmteiler"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Vollbild links"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70 % links"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % links"</string> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 49bfdf18b1e6..cef433815534 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ρυθμίσεις"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Μετάβαση σε διαχωρισμό οθόνης"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Μενού"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Μενού λειτουργίας Picture-in-Picture"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string> <string name="pip_notification_message" msgid="8854051911700302620">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string> <string name="pip_play" msgid="3496151081459417097">"Αναπαραγωγή"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Η εφαρμογή ίσως να μην λειτουργήσει σε δευτερεύουσα οθόνη."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Η εφαρμογή δεν υποστηρίζει την εκκίνηση σε δευτερεύουσες οθόνες."</string> <string name="accessibility_divider" msgid="703810061635792791">"Διαχωριστικό οθόνης"</string> + <string name="divider_title" msgid="5482989479865361192">"Διαχωριστικό οθόνης"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Αριστερή πλήρης οθόνη"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Αριστερή 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Αριστερή 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index 081a01a49249..6a226edb7346 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Picture-in-picture menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="3496151081459417097">"Play"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string> <string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string> + <string name="divider_title" msgid="5482989479865361192">"Split screen divider"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index 081a01a49249..6a226edb7346 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Picture-in-picture menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="3496151081459417097">"Play"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string> <string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string> + <string name="divider_title" msgid="5482989479865361192">"Split screen divider"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index 081a01a49249..6a226edb7346 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Picture-in-picture menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="3496151081459417097">"Play"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string> <string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string> + <string name="divider_title" msgid="5482989479865361192">"Split screen divider"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index 081a01a49249..6a226edb7346 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Picture-in-picture menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="3496151081459417097">"Play"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string> <string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string> + <string name="divider_title" msgid="5482989479865361192">"Split screen divider"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index afc14b821d62..7a3738988776 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -22,6 +22,7 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Picture-in-Picture Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="3496151081459417097">"Play"</string> @@ -36,6 +37,7 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string> <string name="accessibility_divider" msgid="703810061635792791">"Split-screen divider"</string> + <string name="divider_title" msgid="5482989479865361192">"Split-screen divider"</string> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Left full screen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Left 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index b376b7881333..77626afffd6a 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en modo de Pantalla en pantalla"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string> <string name="pip_play" msgid="3496151081459417097">"Reproducir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Es posible que la app no funcione en una pantalla secundaria."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"La app no puede iniciarse en pantallas secundarias."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalla dividida"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Pantalla izquierda completa"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Izquierda: 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Izquierda: 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 79c1f90a4b8d..f813324cca4c 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ajustes"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en imagen en imagen"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string> <string name="pip_play" msgid="3496151081459417097">"Reproducir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Es posible que la aplicación no funcione en una pantalla secundaria."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"La aplicación no se puede abrir en pantallas secundarias."</string> <string name="accessibility_divider" msgid="703810061635792791">"Dividir la pantalla"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Pantalla izquierda completa"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Izquierda 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Izquierda 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index a7fead6af9aa..9d9e5bc33b8d 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Seaded"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ava jagatud ekraanikuva"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menüü"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string> <string name="pip_play" msgid="3496151081459417097">"Esita"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Rakendus ei pruugi teisesel ekraanil töötada."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Rakendus ei toeta teisestel ekraanidel käivitamist."</string> <string name="accessibility_divider" msgid="703810061635792791">"Ekraanijagaja"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Vasak täisekraan"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Vasak: 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vasak: 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index e7530c9690a7..5894a0ec731f 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ezarpenak"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Sartu pantaila zatituan"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menua"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea nahi ez baduzu, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string> <string name="pip_play" msgid="3496151081459417097">"Erreproduzitu"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Baliteke aplikazioak ez funtzionatzea bigarren mailako pantailetan."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikazioa ezin da abiarazi bigarren mailako pantailatan."</string> <string name="accessibility_divider" msgid="703810061635792791">"Pantaila-zatitzailea"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ezarri ezkerraldea pantaila osoan"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Ezarri ezkerraldea % 70en"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ezarri ezkerraldea % 50en"</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 66a657e36c13..bc003ccde4eb 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"تنظیمات"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ورود به حالت «صفحهٔ دونیمه»"</string> <string name="pip_menu_title" msgid="5393619322111827096">"منو"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> درحالت تصویر در تصویر است"</string> <string name="pip_notification_message" msgid="8854051911700302620">"اگر نمیخواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و آن را خاموش کنید."</string> <string name="pip_play" msgid="3496151081459417097">"پخش"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ممکن است برنامه در نمایشگر ثانویه کار نکند."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"برنامه از راهاندازی در نمایشگرهای ثانویه پشتیبانی نمیکند."</string> <string name="accessibility_divider" msgid="703810061635792791">"تقسیمکننده صفحه"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"تمامصفحه چپ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"٪۷۰ چپ"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"٪۵۰ چپ"</string> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index eaf369ad0486..2735be2d50fc 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Asetukset"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Avaa jaettu näyttö"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Valikko"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string> <string name="pip_play" msgid="3496151081459417097">"Toista"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Sovellus ei ehkä toimi toissijaisella näytöllä."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Sovellus ei tue käynnistämistä toissijaisilla näytöillä."</string> <string name="accessibility_divider" msgid="703810061635792791">"Näytön jakaja"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Vasen koko näytölle"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Vasen 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vasen 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 8f614c56db14..f016134fbbff 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entrer dans l\'écran partagé"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string> <string name="pip_play" msgid="3496151081459417097">"Lire"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'application ne peut pas être lancée sur des écrans secondaires."</string> <string name="accessibility_divider" msgid="703810061635792791">"Séparateur d\'écran partagé"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Plein écran à la gauche"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70 % à la gauche"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % à la gauche"</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index ec3e1b33a4fa..f1f8abe77d4c 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accéder à l\'écran partagé"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string> <string name="pip_play" msgid="3496151081459417097">"Lecture"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'application ne peut pas être lancée sur des écrans secondaires."</string> <string name="accessibility_divider" msgid="703810061635792791">"Séparateur d\'écran partagé"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Écran de gauche en plein écran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Écran de gauche à 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Écran de gauche à 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 651353d89319..60674249f4d4 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Inserir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca a configuración para abrir as opcións e desactivar a función."</string> <string name="pip_play" msgid="3496151081459417097">"Reproducir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"É posible que a aplicación non funcione nunha pantalla secundaria."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"A aplicación non se pode iniciar en pantallas secundarias."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalla dividida"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Pantalla completa á esquerda"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70 % á esquerda"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % á esquerda"</string> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index 3543be0bda07..4e4d41c4faf0 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"સેટિંગ"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"વિભાજિત સ્ક્રીન મોડમાં દાખલ થાઓ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"મેનૂ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string> <string name="pip_notification_message" msgid="8854051911700302620">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string> <string name="pip_play" msgid="3496151081459417097">"ચલાવો"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ઍપ્લિકેશન ગૌણ ડિસ્પ્લે પર કદાચ કામ ન કરે."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ઍપ્લિકેશન ગૌણ ડિસ્પ્લે પર લૉન્ચનું સમર્થન કરતી નથી."</string> <string name="accessibility_divider" msgid="703810061635792791">"સ્પ્લિટ-સ્ક્રીન વિભાજક"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ડાબી પૂર્ણ સ્ક્રીન"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ડાબે 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ડાબે 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 87ac5d64ff85..dad0db833bd3 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन मोड में जाएं"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेन्यू"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"पिक्चर में पिक्चर\" के अंदर है"</string> <string name="pip_notification_message" msgid="8854051911700302620">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने के लिए टैप करें और उसे बंद करें ."</string> <string name="pip_play" msgid="3496151081459417097">"चलाएं"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"हो सकता है कि ऐप प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर काम न करे."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर ऐप लॉन्च नहीं किया जा सकता."</string> <string name="accessibility_divider" msgid="703810061635792791">"विभाजित स्क्रीन विभाजक"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"बाईं स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"बाईं स्क्रीन को 70% बनाएं"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"बाईं स्क्रीन को 50% बनाएं"</string> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index cb4f424cf317..ad25eb941d99 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvorite podijeljeni zaslon"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Izbornik"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduciraj"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće funkcionirati na sekundarnom zaslonu."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim zaslonima."</string> <string name="accessibility_divider" msgid="703810061635792791">"Razdjelnik podijeljenog zaslona"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Lijevi zaslon u cijeli zaslon"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Lijevi zaslon na 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Lijevi zaslon na 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index 635f4dad8f89..9b657b140db4 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Beállítások"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Váltás osztott képernyőre"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string> <string name="pip_play" msgid="3496151081459417097">"Lejátszás"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Előfordulhat, hogy az alkalmazás nem működik másodlagos kijelzőn."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Az alkalmazást nem lehet másodlagos kijelzőn elindítani."</string> <string name="accessibility_divider" msgid="703810061635792791">"Elválasztó az osztott nézetben"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Bal oldali teljes képernyőre"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Bal oldali 70%-ra"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Bal oldali 50%-ra"</string> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index da382c113797..41bcb8f16e7a 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Կարգավորումներ"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Մտնել տրոհված էկրանի ռեժիմ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Ընտրացանկ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string> <string name="pip_play" msgid="3496151081459417097">"Նվագարկել"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Հավելվածը կարող է չաշխատել լրացուցիչ էկրանի վրա"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Հավելվածը չի աջակցում գործարկումը լրացուցիչ էկրանների վրա"</string> <string name="accessibility_divider" msgid="703810061635792791">"Տրոհված էկրանի բաժանիչ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ձախ էկրանը՝ լիաէկրան"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Ձախ էկրանը՝ 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ձախ էկրանը՝ 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index cd795390128b..0245b459a763 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Setelan"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Masuk ke mode layar terpisah"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string> <string name="pip_play" msgid="3496151081459417097">"Putar"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikasi mungkin tidak berfungsi pada layar sekunder."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikasi tidak mendukung peluncuran pada layar sekunder."</string> <string name="accessibility_divider" msgid="703810061635792791">"Pembagi layar terpisah"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Layar penuh di kiri"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Kiri 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kiri 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 37141b74005c..bcae730231f8 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Stillingar"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Opna skjáskiptingu"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Valmynd"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string> <string name="pip_play" msgid="3496151081459417097">"Spila"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Hugsanlegt er að forritið virki ekki á öðrum skjá."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Forrit styður ekki opnun á öðrum skjá."</string> <string name="accessibility_divider" msgid="703810061635792791">"Skjáskipting"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Vinstri á öllum skjánum"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Vinstri 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vinstri 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index b63e76466b6e..0f586a722ebf 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Impostazioni"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accedi a schermo diviso"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string> <string name="pip_play" msgid="3496151081459417097">"Riproduci"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"L\'app potrebbe non funzionare su un display secondario."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'app non supporta l\'avvio su display secondari."</string> <string name="accessibility_divider" msgid="703810061635792791">"Strumento per schermo diviso"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Schermata sinistra a schermo intero"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Schermata sinistra al 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Schermata sinistra al 50%"</string> @@ -72,8 +76,7 @@ <string name="notification_bubble_title" msgid="6082910224488253378">"Fumetto"</string> <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestisci"</string> <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Fumetto ignorato."</string> - <!-- no translation found for restart_button_description (6712141648865547958) --> - <skip /> + <string name="restart_button_description" msgid="6712141648865547958">"Tocca per riavviare quest\'app per una migliore visualizzazione."</string> <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 0e500eafd805..16aa4df76930 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"הגדרות"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"כניסה למסך המפוצל"</string> <string name="pip_menu_title" msgid="5393619322111827096">"תפריט"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string> <string name="pip_notification_message" msgid="8854051911700302620">"אם אינך רוצה שהתכונה הזו תשמש את <xliff:g id="NAME">%s</xliff:g>, יש להקיש כדי לפתוח את ההגדרות ולהשבית את התכונה."</string> <string name="pip_play" msgid="3496151081459417097">"הפעלה"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ייתכן שהאפליקציה לא תפעל במסך משני."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"האפליקציה אינה תומכת בהפעלה במסכים משניים."</string> <string name="accessibility_divider" msgid="703810061635792791">"מחלק מסך מפוצל"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"מסך שמאלי מלא"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"שמאלה 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"שמאלה 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 34ed9c72da0e..67f58b8867f9 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"分割画面に切り替え"</string> <string name="pip_menu_title" msgid="5393619322111827096">"メニュー"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string> <string name="pip_play" msgid="3496151081459417097">"再生"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"アプリはセカンダリ ディスプレイでは動作しないことがあります。"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"アプリはセカンダリ ディスプレイでの起動に対応していません。"</string> <string name="accessibility_divider" msgid="703810061635792791">"分割画面の分割線"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"左全画面"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"左 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"左 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 14b26c1932cc..9220a36f56be 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"პარამეტრები"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"გაყოფილ ეკრანში შესვლა"</string> <string name="pip_menu_title" msgid="5393619322111827096">"მენიუ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string> <string name="pip_notification_message" msgid="8854051911700302620">"თუ არ გსურთ, რომ <xliff:g id="NAME">%s</xliff:g> ამ ფუნქციას იყენებდეს, აქ შეხებით შეგიძლიათ გახსნათ პარამეტრები და გამორთოთ ის."</string> <string name="pip_play" msgid="3496151081459417097">"დაკვრა"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"აპმა შეიძლება არ იმუშაოს მეორეულ ეკრანზე."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"აპს არ გააჩნია მეორეული ეკრანის მხარდაჭერა."</string> <string name="accessibility_divider" msgid="703810061635792791">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"მარცხენა ნაწილის სრულ ეკრანზე გაშლა"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"მარცხენა ეკრანი — 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"მარცხენა ეკრანი — 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index c42efdc4cf25..9ccd5f2c7ee5 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Параметрлер"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Бөлінген экранға кіру"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Mәзір"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"суреттегі сурет\" режимінде"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string> <string name="pip_play" msgid="3496151081459417097">"Ойнату"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Қолданба қосымша дисплейде жұмыс істемеуі мүмкін."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Қолданба қосымша дисплейлерде іске қосуды қолдамайды."</string> <string name="accessibility_divider" msgid="703810061635792791">"Бөлінген экран бөлгіші"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Сол жағын толық экранға шығару"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70% сол жақта"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% сол жақта"</string> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 302b25e5bad2..fbf7add21a39 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ការកំណត់"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ចូលមុខងារបំបែកអេក្រង់"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ម៉ឺនុយ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ប្រសិនបើអ្នកមិនចង់ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើមុខងារនេះ សូមចុចបើកការកំណត់ រួចបិទវា។"</string> <string name="pip_play" msgid="3496151081459417097">"លេង"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"កម្មវិធីនេះប្រហែលជាមិនដំណើរការនៅលើអេក្រង់បន្ទាប់បន្សំទេ។"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"កម្មវិធីនេះមិនអាចចាប់ផ្តើមនៅលើអេក្រង់បន្ទាប់បន្សំបានទេ។"</string> <string name="accessibility_divider" msgid="703810061635792791">"កម្មវិធីចែកអេក្រង់បំបែក"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"អេក្រង់ពេញខាងឆ្វេង"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ឆ្វេង 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ឆ្វេង 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 2b3aa0791336..62a2d52d8265 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ಗೆ ಪ್ರವೇಶಿಸಿ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ಮೆನು"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವಾಗಿದೆ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಲು ಮತ್ತು ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="pip_play" msgid="3496151081459417097">"ಪ್ಲೇ"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕಾರ್ಯ ನಿರ್ವಹಿಸದೇ ಇರಬಹುದು."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಪ್ರಾರಂಭಿಸುವಿಕೆಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string> <string name="accessibility_divider" msgid="703810061635792791">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ಎಡ ಪೂರ್ಣ ಪರದೆ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70% ಎಡಕ್ಕೆ"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% ಎಡಕ್ಕೆ"</string> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 5505955db71a..82c80b81adcf 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"설정"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"화면 분할 모드로 전환"</string> <string name="pip_menu_title" msgid="5393619322111827096">"메뉴"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string> <string name="pip_play" msgid="3496151081459417097">"재생"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"앱이 보조 디스플레이에서 작동하지 않을 수도 있습니다."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"앱이 보조 디스플레이에서의 실행을 지원하지 않습니다."</string> <string name="accessibility_divider" msgid="703810061635792791">"화면 분할기"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"왼쪽 화면 전체화면"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"왼쪽 화면 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"왼쪽 화면 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index d45a9848abc4..0b1f83ffcb6e 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Жөндөөлөр"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Экранды бөлүү режимине өтүү"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string> <string name="pip_play" msgid="3496151081459417097">"Ойнотуу"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Колдонмо кошумча экранда иштебей коюшу мүмкүн."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Колдонмону кошумча экрандарда иштетүүгө болбойт."</string> <string name="accessibility_divider" msgid="703810061635792791">"Экранды бөлгүч"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Сол жактагы экранды толук экран режимине өткөрүү"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Сол жактагы экранды 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Сол жактагы экранды 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 0eeee906070b..ec468a5b625d 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ການຕັ້ງຄ່າ"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ເຂົ້າການແບ່ງໜ້າຈໍ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ເມນູ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string> <string name="pip_play" msgid="3496151081459417097">"ຫຼິ້ນ"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ແອັບອາດບໍ່ສາມາດໃຊ້ໄດ້ໃນໜ້າຈໍທີສອງ."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ແອັບບໍ່ຮອງຮັບການເປີດໃນໜ້າຈໍທີສອງ."</string> <string name="accessibility_divider" msgid="703810061635792791">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ເຕັມໜ້າຈໍຊ້າຍ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ຊ້າຍ 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ຊ້າຍ 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index fc118e217481..fdb51fcca7ee 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Nustatymai"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Įjungti išskaidyto ekrano režimą"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jei nenorite, kad „<xliff:g id="NAME">%s</xliff:g>“ naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string> <string name="pip_play" msgid="3496151081459417097">"Leisti"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Programa gali neveikti antriniame ekrane."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Programa nepalaiko paleisties antriniuose ekranuose."</string> <string name="accessibility_divider" msgid="703810061635792791">"Skaidyto ekrano daliklis"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Kairysis ekranas viso ekrano režimu"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Kairysis ekranas 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kairysis ekranas 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index cd2af07beb7e..ca666cea722b 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Iestatījumi"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Piekļūt ekrāna sadalīšanas režīmam"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Izvēlne"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un izslēgtu funkciju."</string> <string name="pip_play" msgid="3496151081459417097">"Atskaņot"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Lietotne, iespējams, nedarbosies sekundārajā displejā."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Lietotnē netiek atbalstīta palaišana sekundārajos displejos."</string> <string name="accessibility_divider" msgid="703810061635792791">"Ekrāna sadalītājs"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Kreisā daļa pa visu ekrānu"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Pa kreisi 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Pa kreisi 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index c0dff00e6a7c..64b1cbcb5343 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Поставки"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Влези во поделен екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и да ја исклучите."</string> <string name="pip_play" msgid="3496151081459417097">"Пушти"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апликацијата може да не функционира на друг екран."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Апликацијата не поддржува стартување на други екрани."</string> <string name="accessibility_divider" msgid="703810061635792791">"Разделник на поделен екран"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Левиот на цел екран"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Левиот 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Левиот 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index 52ea1c7c3150..6b6af060f93a 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ക്രമീകരണം"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"സ്ക്രീൻ വിഭജന മോഡിൽ പ്രവേശിക്കുക"</string> <string name="pip_menu_title" msgid="5393619322111827096">"മെനു"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിൽ ചിത്രം രീതിയിലാണ്"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കേണ്ടെങ്കിൽ, ടാപ്പ് ചെയ്ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string> <string name="pip_play" msgid="3496151081459417097">"പ്ലേ ചെയ്യുക"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"രണ്ടാം ഡിസ്പ്ലേയിൽ ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"രണ്ടാം ഡിസ്പ്ലേകളിൽ സമാരംഭിക്കുന്നതിനെ ആപ്പ് അനുവദിക്കുന്നില്ല."</string> <string name="accessibility_divider" msgid="703810061635792791">"സ്പ്ലിറ്റ്-സ്ക്രീൻ ഡിവൈഡർ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ഇടത് പൂർണ്ണ സ്ക്രീൻ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ഇടത് 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ഇടത് 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index fd4c4aab1832..2cb48c2c81e1 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Тохиргоо"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Хуваасан дэлгэцийг оруулна уу"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Цэс"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string> <string name="pip_play" msgid="3496151081459417097">"Тоглуулах"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апп хоёрдогч дэлгэцэд ажиллахгүй."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Аппыг хоёрдогч дэлгэцэд эхлүүлэх боломжгүй."</string> <string name="accessibility_divider" msgid="703810061635792791">"\"Дэлгэц хуваах\" хуваагч"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Зүүн талын бүтэн дэлгэц"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Зүүн 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Зүүн 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index b9a165eb6b11..73c709f8f6c4 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग्ज"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन एंटर करा"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेनू"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>ने हे वैशिष्ट्य वापरू नये असे तुम्हाला वाटत असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string> <string name="pip_play" msgid="3496151081459417097">"प्ले करा"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"दुसऱ्या डिस्प्लेवर अॅप कदाचित चालणार नाही."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"दुसऱ्या डिस्प्लेवर अॅप लाँच होणार नाही."</string> <string name="accessibility_divider" msgid="703810061635792791">"विभाजित-स्क्रीन विभाजक"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"डावी फुल स्क्रीन"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"डावी 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"डावी 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 3d81c9a551fa..4368684936ac 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Tetapan"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Masuk skrin pisah"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikan ciri."</string> <string name="pip_play" msgid="3496151081459417097">"Main"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Apl mungkin tidak berfungsi pada paparan kedua."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Apl tidak menyokong pelancaran pada paparan kedua."</string> <string name="accessibility_divider" msgid="703810061635792791">"Pembahagi skrin pisah"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Skrin penuh kiri"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Kiri 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kiri 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 50adfe98d8f9..be61336e0383 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ဆက်တင်များ"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသို့ ဝင်ရန်"</string> <string name="pip_menu_title" msgid="5393619322111827096">"မီနူး"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> သည် နှစ်ခုထပ်၍ကြည့်ခြင်း ဖွင့်ထားသည်"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> အား ဤဝန်ဆောင်မှုကို အသုံးမပြုစေလိုလျှင် ဆက်တင်ကိုဖွင့်ရန် တို့ပြီး ၎င်းဝန်ဆောင်မှုကို ပိတ်လိုက်ပါ။"</string> <string name="pip_play" msgid="3496151081459417097">"ဖွင့်ရန်"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ဤအက်ပ်အနေဖြင့် ဒုတိယဖန်သားပြင်ပေါ်တွင် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ဤအက်ပ်အနေဖြင့် ဖွင့်ရန်စနစ်ကို ဒုတိယဖန်သားပြင်မှ အသုံးပြုရန် ပံ့ပိုးမထားပါ။"</string> <string name="accessibility_divider" msgid="703810061635792791">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ဘယ်ဘက် မျက်နှာပြင်အပြည့်"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ဘယ်ဘက်မျက်နှာပြင် ၇၀%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ဘယ်ဘက် မျက်နှာပြင် ၅၀%"</string> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 74e066ec11fd..ae771e5dc00d 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Innstillinger"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivér delt skjerm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string> <string name="pip_play" msgid="3496151081459417097">"Spill av"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen fungerer kanskje ikke på en sekundær skjerm."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan ikke kjøres på sekundære skjermer."</string> <string name="accessibility_divider" msgid="703810061635792791">"Skilleelement for delt skjerm"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Utvid den venstre delen av skjermen til hele skjermen"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Sett størrelsen på den venstre delen av skjermen til 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Sett størrelsen på den venstre delen av skjermen til 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index b257f9e6d0d3..692e985ef5ce 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिङहरू"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रिन मोड प्रयोग गर्नुहोस्"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेनु"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले सुविधा प्रयोग नगरोस् भन्ने चाहनुहुन्छ भने ट्याप गरेर सेटिङहरू खोल्नुहोस् र यसलाई निष्क्रिय पार्नुहोस्।"</string> <string name="pip_play" msgid="3496151081459417097">"प्ले गर्नुहोस्"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"यो एपले सहायक प्रदर्शनमा काम नगर्नसक्छ।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"अनुप्रयोगले सहायक प्रदर्शनहरूमा लञ्च सुविधालाई समर्थन गर्दैन।"</string> <string name="accessibility_divider" msgid="703810061635792791">"विभाजित-स्क्रिन छुट्याउने"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"बायाँ भाग फुल स्क्रिन"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"बायाँ भाग ७०%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"बायाँ भाग ५०%"</string> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 6ea24a8b3808..55c62aec467c 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Instellingen"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gesplitst scherm openen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en zet je de functie uit."</string> <string name="pip_play" msgid="3496151081459417097">"Afspelen"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App werkt mogelijk niet op een secundair scherm."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App kan niet op secundaire displays worden gestart."</string> <string name="accessibility_divider" msgid="703810061635792791">"Scheiding voor gesplitst scherm"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Linkerscherm op volledig scherm"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Linkerscherm 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Linkerscherm 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index f8c924828d50..1cfda264a093 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ସେଟିଂସ୍"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ମେନୁ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"ଛବି-ଭିତରେ-ଛବି\"ରେ ଅଛି"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ଏହି ବୈଶିଷ୍ଟ୍ୟ <xliff:g id="NAME">%s</xliff:g> ବ୍ୟବହାର ନକରିବାକୁ ଯଦି ଆପଣ ଚାହାଁନ୍ତି, ସେଟିଙ୍ଗ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଏହା ଅଫ୍ କରିଦିଅନ୍ତୁ।"</string> <string name="pip_play" msgid="3496151081459417097">"ପ୍ଲେ କରନ୍ତୁ"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ କାମ ନକରିପାରେ।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ ଲଞ୍ଚ ସପୋର୍ଟ କରେ ନାହିଁ।"</string> <string name="accessibility_divider" msgid="703810061635792791">"ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନ ବିଭାଜକ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ବାମ ପଟକୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍ କରନ୍ତୁ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ବାମ ପଟକୁ 70% କରନ୍ତୁ"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ବାମ ପଟକୁ 50% କରନ୍ତୁ"</string> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index b80da0ba4e57..5c0c60182915 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ਸੈਟਿੰਗਾਂ"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ਮੀਨੂ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਅੰਦਰ-ਤਸਵੀਰ ਵਿੱਚ ਹੈ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ਜੇਕਰ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string> <string name="pip_play" msgid="3496151081459417097">"ਚਲਾਓ"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇ \'ਤੇ ਕੰਮ ਨਾ ਕਰੇ।"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇਆਂ \'ਤੇ ਲਾਂਚ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string> <string name="accessibility_divider" msgid="703810061635792791">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ਖੱਬੇ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ਖੱਬੇ 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ਖੱਬੇ 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index bdd44dd8a743..1879649ae8bd 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ustawienia"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Włącz podzielony ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i wyłącz ją."</string> <string name="pip_play" msgid="3496151081459417097">"Odtwórz"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacja może nie działać na dodatkowym ekranie."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacja nie obsługuje uruchamiania na dodatkowych ekranach."</string> <string name="accessibility_divider" msgid="703810061635792791">"Linia dzielenia ekranu"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Lewa część ekranu na pełnym ekranie"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70% lewej części ekranu"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% lewej części ekranu"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index b9e41eae5de9..d3fb14da2824 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduzir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"É possível que o app não funcione em uma tela secundária."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"O app não é compatível com a inicialização em telas secundárias."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor de tela"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Lado esquerdo em tela cheia"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Esquerda a 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Esquerda a 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index c1e57d8c9c97..1d78dcb16f2f 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Definições"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aceder ao ecrã dividido"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"A app <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se não pretende que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduzir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"A app pode não funcionar num ecrã secundário."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"A app não é compatível com o início em ecrãs secundários."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor do ecrã dividido"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ecrã esquerdo inteiro"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"70% no ecrã esquerdo"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% no ecrã esquerdo"</string> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index b9e41eae5de9..d3fb14da2824 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> <string name="pip_play" msgid="3496151081459417097">"Reproduzir"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"É possível que o app não funcione em uma tela secundária."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"O app não é compatível com a inicialização em telas secundárias."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divisor de tela"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Lado esquerdo em tela cheia"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Esquerda a 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Esquerda a 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index c49bf9dc231c..7aaa21b18bd9 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Setări"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accesați ecranul împărțit"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string> <string name="pip_play" msgid="3496151081459417097">"Redați"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Este posibil ca aplicația să nu funcționeze pe un ecran secundar."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplicația nu acceptă lansare pe ecrane secundare."</string> <string name="accessibility_divider" msgid="703810061635792791">"Separator pentru ecranul împărțit"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Partea stângă pe ecran complet"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Partea stângă: 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Partea stângă: 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index ffe031d86725..7270449bdfea 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Включить разделение экрана"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string> <string name="pip_notification_message" msgid="8854051911700302620">"Чтобы отключить эту функцию для приложения \"<xliff:g id="NAME">%s</xliff:g>\", перейдите в настройки."</string> <string name="pip_play" msgid="3496151081459417097">"Воспроизвести"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Приложение может не работать на дополнительном экране"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Приложение не поддерживает запуск на дополнительных экранах"</string> <string name="accessibility_divider" msgid="703810061635792791">"Разделитель экрана"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Левый во весь экран"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Левый на 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Левый на 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index b27e1b9bc94a..ef25c0ad3480 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"සැකසීම්"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"බෙදුම් තිරයට ඇතුළු වන්න"</string> <string name="pip_menu_title" msgid="5393619322111827096">"මෙනුව"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> පින්තූරය-තුළ-පින්තූරය තුළ වේ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්රියාවිරහිත කරන්න."</string> <string name="pip_play" msgid="3496151081459417097">"ධාවනය කරන්න"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"යෙදුම ද්විතියික සංදර්ශකයක ක්රියා නොකළ හැකිය."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"යෙදුම ද්විතීයික සංදර්ශක මත දියත් කිරීම සඳහා සහාය නොදක්වයි."</string> <string name="accessibility_divider" msgid="703810061635792791">"බෙදුම්-තිර වෙන්කරණය"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"වම් පූර්ණ තිරය"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"වම් 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"වම් 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index b5bedf79f3ba..069bd1d2d5b6 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavenia"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Prejsť na rozdelenú obrazovku"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Ponuka"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string> <string name="pip_play" msgid="3496151081459417097">"Prehrať"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikácia nemusí fungovať na sekundárnej obrazovke."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikácia nepodporuje spúšťanie na sekundárnych obrazovkách."</string> <string name="accessibility_divider" msgid="703810061635792791">"Rozdeľovač obrazovky"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ľavá – na celú obrazovku"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Ľavá – 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ľavá – 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index ac926b9ee8db..fe5813eb266f 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavitve"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Vklopi razdeljen zaslon"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v načinu slika v sliki"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string> <string name="pip_play" msgid="3496151081459417097">"Predvajaj"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija morda ne bo delovala na sekundarnem zaslonu."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podpira zagona na sekundarnih zaslonih."</string> <string name="accessibility_divider" msgid="703810061635792791">"Razdelilnik zaslonov"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Levi v celozaslonski način"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Levi 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Levi 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 07c52fe4251a..79c5334380fe 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Cilësimet"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Hyr në ekranin e ndarë"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyja"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string> <string name="pip_play" msgid="3496151081459417097">"Luaj"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacioni mund të mos funksionojë në një ekran dytësor."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacioni nuk mbështet nisjen në ekrane dytësore."</string> <string name="accessibility_divider" msgid="703810061635792791">"Ndarësi i ekranit të ndarë"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ekrani i plotë majtas"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Majtas 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Majtas 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 0289dd105ee5..a1b8e03868ec 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Подешавања"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Уђи на подељени екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не желите да <xliff:g id="NAME">%s</xliff:g> користи ову функцију, додирните да бисте отворили подешавања и искључили је."</string> <string name="pip_play" msgid="3496151081459417097">"Пусти"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апликација можда неће функционисати на секундарном екрану."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Апликација не подржава покретање на секундарним екранима."</string> <string name="accessibility_divider" msgid="703810061635792791">"Разделник подељеног екрана"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Режим целог екрана за леви екран"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Леви екран 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Леви екран 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index cfdb1ddcf377..90e2acf40e36 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Inställningar"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Starta delad skärm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Om du inte vill att den här funktionen används i <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string> <string name="pip_play" msgid="3496151081459417097">"Spela upp"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen kanske inte fungerar på en sekundär skärm."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan inte köras på en sekundär skärm."</string> <string name="accessibility_divider" msgid="703810061635792791">"Avdelare för delad skärm"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Helskärm på vänster skärm"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Vänster 70 %"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vänster 50 %"</string> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 383e9bb6bbfa..b231ce0152d8 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Mipangilio"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Weka skrini iliyogawanywa"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> itumie kipengele hiki, gusa ili ufungue mipangilio na uizime."</string> <string name="pip_play" msgid="3496151081459417097">"Cheza"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Huenda programu isifanye kazi kwenye dirisha lingine."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Programu hii haiwezi kufunguliwa kwenye madirisha mengine."</string> <string name="accessibility_divider" msgid="703810061635792791">"Kitenganishi cha skrini inayogawanywa"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Skrini nzima ya kushoto"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Kushoto 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kushoto 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index cc512f3c48aa..e12868bc897a 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"அமைப்புகள்"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"திரைப் பிரிப்பு பயன்முறைக்குச் செல்"</string> <string name="pip_menu_title" msgid="5393619322111827096">"மெனு"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால் இங்கு தட்டி அமைப்புகளைத் திறந்து இதை முடக்கவும்."</string> <string name="pip_play" msgid="3496151081459417097">"இயக்கு"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"இரண்டாம்நிலைத் திரையில் ஆப்ஸ் வேலை செய்யாமல் போகக்கூடும்."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"இரண்டாம்நிலைத் திரைகளில் பயன்பாட்டைத் தொடங்க முடியாது."</string> <string name="accessibility_divider" msgid="703810061635792791">"திரையைப் பிரிக்கும் பிரிப்பான்"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"இடது புறம் முழுத் திரை"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"இடது புறம் 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"இடது புறம் 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index cdbe021add47..305229e8932c 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"సెట్టింగ్లు"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"స్ప్లిట్ స్క్రీన్ను ఎంటర్ చేయండి"</string> <string name="pip_menu_title" msgid="5393619322111827096">"మెనూ"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్లను తెరవడానికి ట్యాప్ చేసి, దీన్ని ఆఫ్ చేయండి."</string> <string name="pip_play" msgid="3496151081459417097">"ప్లే చేయి"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్ప్లేలో యాప్ పని చేయకపోవచ్చు."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string> <string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ఎడమవైపు ఫుల్-స్క్రీన్"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ఎడమవైపు 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ఎడమవైపు 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 136a81c06c4f..ed7e75acbac4 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"การตั้งค่า"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"เข้าสู่โหมดแบ่งหน้าจอ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"เมนู"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> <string name="pip_play" msgid="3496151081459417097">"เล่น"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"แอปอาจไม่ทำงานในจอแสดงผลรอง"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"แอปไม่รองรับการเรียกใช้ในจอแสดงผลรอง"</string> <string name="accessibility_divider" msgid="703810061635792791">"เส้นแบ่งหน้าจอ"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"เต็มหน้าจอทางซ้าย"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ซ้าย 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ซ้าย 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 4d32af36cabe..261bc742df72 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Mga Setting"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Pumasok sa split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Kung ayaw mong magamit ni <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string> <string name="pip_play" msgid="3496151081459417097">"I-play"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Maaaring hindi gumana ang app sa pangalawang display."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Hindi sinusuportahan ng app ang paglulunsad sa mga pangalawang display."</string> <string name="accessibility_divider" msgid="703810061635792791">"Divider ng split-screen"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"I-full screen ang nasa kaliwa"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Gawing 70% ang nasa kaliwa"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Gawing 50% ang nasa kaliwa"</string> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index f3ab37065270..8c9b2c9508de 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana geç"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve söz konusu özelliği kapatın."</string> <string name="pip_play" msgid="3496151081459417097">"Oynat"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Uygulama ikincil ekranda çalışmayabilir."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Uygulama ikincil ekranlarda başlatılmayı desteklemiyor."</string> <string name="accessibility_divider" msgid="703810061635792791">"Bölünmüş ekran ayırıcı"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Solda tam ekran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Solda %70"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Solda %50"</string> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index d7d82cb56ac5..db548ebb8110 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Налаштування"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Розділити екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string> <string name="pip_notification_message" msgid="8854051911700302620">"Щоб додаток <xliff:g id="NAME">%s</xliff:g> не використовував цю функцію, вимкніть її в налаштуваннях."</string> <string name="pip_play" msgid="3496151081459417097">"Відтворити"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Додаток може не працювати на додатковому екрані."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Додаток не підтримує запуск на додаткових екранах."</string> <string name="accessibility_divider" msgid="703810061635792791">"Розділювач екрана"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ліве вікно на весь екран"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Ліве вікно на 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ліве вікно на 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 4a8476aebe18..ea63e9d55aa3 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"ترتیبات"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"اسپلٹ اسکرین تک رسائی"</string> <string name="pip_menu_title" msgid="5393619322111827096">"مینو"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string> <string name="pip_notification_message" msgid="8854051911700302620">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کے لیے تھپتھپا کر اسے آف کرے۔"</string> <string name="pip_play" msgid="3496151081459417097">"چلائیں"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ممکن ہے ایپ ثانوی ڈسپلے پر کام نہ کرے۔"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ایپ ثانوی ڈسپلیز پر شروعات کا تعاون نہیں کرتی۔"</string> <string name="accessibility_divider" msgid="703810061635792791">"سپلٹ اسکرین تقسیم کار"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"بائیں فل اسکرین"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"بائیں %70"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"بائیں %50"</string> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index 8a4eac3bb657..a334b0ec6669 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Sozlamalar"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ajratilgan ekranga kirish"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali faolsizlantirish mumkin."</string> <string name="pip_play" msgid="3496151081459417097">"Ijro"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Bu ilova qo‘shimcha ekranda ishlamasligi mumkin."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Bu ilova qo‘shimcha ekranlarda ishga tushmaydi."</string> <string name="accessibility_divider" msgid="703810061635792791">"Ekranni ikkiga bo‘lish chizig‘i"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Chapda to‘liq ekran"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Chapda 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Chapda 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 2f8fe6076c68..03f500ac3ece 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Cài đặt"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Truy cập chế độ chia đôi màn hình"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string> <string name="pip_play" msgid="3496151081459417097">"Phát"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Ứng dụng có thể không hoạt động trên màn hình phụ."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ."</string> <string name="accessibility_divider" msgid="703810061635792791">"Bộ chia chia đôi màn hình"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Toàn màn hình bên trái"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Trái 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Trái 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index ab44fb1d2488..2b04f6e35c4e 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"设置"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"进入分屏模式"</string> <string name="pip_menu_title" msgid="5393619322111827096">"菜单"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想让“<xliff:g id="NAME">%s</xliff:g>”使用此功能,请点按以打开设置,然后关闭此功能。"</string> <string name="pip_play" msgid="3496151081459417097">"播放"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"应用可能无法在辅显示屏上正常运行。"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"应用不支持在辅显示屏上启动。"</string> <string name="accessibility_divider" msgid="703810061635792791">"分屏分隔线"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"左侧全屏"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"左侧 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"左侧 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 8fb7adebe930..253869b0a871 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割螢幕"</string> <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string> <string name="pip_play" msgid="3496151081459417097">"播放"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"應用程式可能無法在次要顯示屏上運作。"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"應用程式無法在次要顯示屏上啟動。"</string> <string name="accessibility_divider" msgid="703810061635792791">"分割畫面分隔線"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"左邊全螢幕"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"左邊 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"左邊 50%"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index 45de4156084b..6109cbb7f5ab 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割畫面"</string> <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string> <string name="pip_play" msgid="3496151081459417097">"播放"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"應用程式可能無法在次要顯示器上運作。"</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"應用程式無法在次要顯示器上啟動。"</string> <string name="accessibility_divider" msgid="703810061635792791">"分割畫面分隔線"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"以全螢幕顯示左側畫面"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"以 70% 的螢幕空間顯示左側畫面"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"以 50% 的螢幕空間顯示左側畫面"</string> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 7c31a166e825..8af4f9fd5be3 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -22,6 +22,8 @@ <string name="pip_phone_settings" msgid="5468987116750491918">"Izilungiselelo"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Faka ukuhlukanisa isikrini"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Imenyu"</string> + <!-- no translation found for pip_menu_accessibility_title (8129016817688656249) --> + <skip /> <string name="pip_notification_title" msgid="1347104727641353453">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Uma ungafuni i-<xliff:g id="NAME">%s</xliff:g> ukuthi isebenzise lesi sici, thepha ukuze uvule izilungiselelo uphinde uyivale."</string> <string name="pip_play" msgid="3496151081459417097">"Dlala"</string> @@ -36,6 +38,8 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Uhlelo lokusebenza kungenzeka lungasebenzi kusibonisi sesibili."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Uhlelo lokusebenza alusekeli ukuqalisa kuzibonisi zesibili."</string> <string name="accessibility_divider" msgid="703810061635792791">"Isihlukanisi sokuhlukanisa isikrini"</string> + <!-- no translation found for divider_title (5482989479865361192) --> + <skip /> <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Isikrini esigcwele esingakwesokunxele"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"Kwesokunxele ngo-70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kwesokunxele ngo-50%"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java deleted file mode 100644 index 73fd6931066d..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 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.wm.shell; - -import com.android.wm.shell.common.annotations.ExternalThread; - -import java.io.PrintWriter; - -/** - * An entry point into the shell for dumping shell internal state and running adb commands. - * - * Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}. - */ -@ExternalThread -public interface ShellCommandHandler { - /** - * Dumps the shell state. - */ - void dump(PrintWriter pw); - - /** - * Handles a shell command. - */ - boolean handleCommand(final String[] args, PrintWriter pw); -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java deleted file mode 100644 index d7010b174744..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2019 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.wm.shell; - -import com.android.wm.shell.common.annotations.ExternalThread; - -/** - * An entry point into the shell for initializing shell internal state. - */ -@ExternalThread -public interface ShellInit { - /** - * Initializes the shell state. - */ - void init(); -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java new file mode 100644 index 000000000000..82b0270698e4 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java @@ -0,0 +1,80 @@ +/* + * 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.wm.shell.activityembedding; + +import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; + +import android.content.Context; +import android.os.IBinder; +import android.view.SurfaceControl; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; +import android.window.WindowContainerTransaction; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.wm.shell.transition.Transitions; + +/** + * Responsible for handling ActivityEmbedding related transitions. + */ +public class ActivityEmbeddingController implements Transitions.TransitionHandler { + + private final Context mContext; + private final Transitions mTransitions; + + public ActivityEmbeddingController(Context context, Transitions transitions) { + mContext = context; + mTransitions = transitions; + } + + /** Registers to handle transitions. */ + public void init() { + mTransitions.addHandler(this); + } + + @Override + public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + // TODO(b/207070762) Handle AE animation as a part of other transitions. + // Only handle the transition if all containers are embedded. + for (TransitionInfo.Change change : info.getChanges()) { + if (!isEmbedded(change)) { + return false; + } + } + + // TODO(b/207070762) Implement AE animation. + startTransaction.apply(); + finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); + return true; + } + + @Nullable + @Override + public WindowContainerTransaction handleRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request) { + return null; + } + + private static boolean isEmbedded(@NonNull TransitionInfo.Change change) { + return (change.getFlags() & FLAG_IS_EMBEDDED) != 0; + } +} 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 8c0affb0a432..86f9d5b534f4 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 @@ -29,6 +29,13 @@ import com.android.wm.shell.common.annotations.ExternalThread; public interface BackAnimation { /** + * Returns a binder that can be passed to an external process to update back animations. + */ + default IBackAnimation createExternalInterface() { + return null; + } + + /** * Called when a {@link MotionEvent} is generated by a back gesture. * * @param touchX the X touch position of the {@link MotionEvent}. @@ -47,13 +54,6 @@ public interface BackAnimation { void setTriggerBack(boolean triggerBack); /** - * Returns a binder that can be passed to an external process to update back animations. - */ - default IBackAnimation createExternalInterface() { - return null; - } - - /** * Sets the threshold values that defining edge swipe behavior. * @param triggerThreshold the min threshold to trigger back. * @param progressThreshold the max threshold to keep progressing back animation. 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 e35e4ac8881c..80cf8c3d2de4 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 @@ -32,11 +32,13 @@ import android.graphics.PointF; import android.hardware.HardwareBuffer; import android.net.Uri; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings.Global; import android.util.Log; +import android.view.IWindowFocusObserver; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; @@ -110,6 +112,24 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont MAX_TRANSITION_DURATION); }; + @VisibleForTesting + final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() { + @Override + public void focusGained(IBinder inputToken) { } + @Override + public void focusLost(IBinder inputToken) { + mShellExecutor.execute(() -> { + if (!mBackGestureStarted || mTransitionInProgress) { + // If an uninterruptible transition is already in progress, we should ignore + // this due to the transition may cause focus lost. (alpha = 0) + return; + } + setTriggerBack(false); + onGestureFinished(false); + }); + } + }; + public BackAnimationController( @NonNull @ShellMainThread ShellExecutor shellExecutor, @NonNull @ShellBackgroundThread Handler backgroundHandler, @@ -269,17 +289,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont // 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(touchX, touchY); + onGestureStarted(touchX, touchY); } 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", keyAction); - onGestureFinished(); + onGestureFinished(true); } } - private void initAnimation(float touchX, float touchY) { + private void onGestureStarted(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."); @@ -291,7 +311,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont try { boolean requestAnimation = mEnableAnimations.get(); - mBackNavigationInfo = mActivityTaskManager.startBackNavigation(requestAnimation); + mBackNavigationInfo = + mActivityTaskManager.startBackNavigation(requestAnimation, mFocusObserver); onBackNavigationInfoReceived(mBackNavigationInfo); } catch (RemoteException remoteException) { Log.e(TAG, "Failed to initAnimation", remoteException); @@ -379,11 +400,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont dispatchOnBackProgressed(targetCallback, backEvent); } - private void onGestureFinished() { + private void onGestureFinished(boolean fromTouch) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack); - if (!mBackGestureStarted || mBackNavigationInfo == null) { + if (fromTouch) { + // Let touch reset the flag otherwise it will start a new back navigation and refresh + // the info when received a new move event. + mBackGestureStarted = false; + } + + if (mTransitionInProgress || mBackNavigationInfo == null) { return; } + int backType = mBackNavigationInfo.getType(); boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType); IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher @@ -473,7 +501,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private void finishAnimation() { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishAnimation()"); - mBackGestureStarted = false; mTouchEventDelta.set(0, 0); mInitTouchLocation.set(0, 0); BackNavigationInfo backNavigationInfo = mBackNavigationInfo; @@ -483,6 +510,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont if (backNavigationInfo == null) { return; } + RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget(); if (animationTarget != null) { if (animationTarget.leash != null && animationTarget.leash.isValid()) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 62aa7fe28728..d7f1292cb717 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -101,6 +101,8 @@ import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.PinnedStackListenerForwarder; +import com.android.wm.shell.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.ShellController; import java.io.PrintWriter; import java.util.ArrayList; @@ -119,7 +121,7 @@ import java.util.function.IntConsumer; * * The controller manages addition, removal, and visible state of bubbles on screen. */ -public class BubbleController { +public class BubbleController implements ConfigurationChangeListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; @@ -155,6 +157,7 @@ public class BubbleController { private final DisplayController mDisplayController; private final TaskViewTransitions mTaskViewTransitions; private final SyncTransactionQueue mSyncQueue; + private final ShellController mShellController; // Used to post to main UI thread private final ShellExecutor mMainExecutor; @@ -224,6 +227,7 @@ public class BubbleController { public BubbleController(Context context, + ShellController shellController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, FloatingContentCoordinator floatingContentCoordinator, @@ -246,6 +250,7 @@ public class BubbleController { TaskViewTransitions taskViewTransitions, SyncTransactionQueue syncQueue) { mContext = context; + mShellController = shellController; mLauncherApps = launcherApps; mBarService = statusBarService == null ? IStatusBarService.Stub.asInterface( @@ -414,6 +419,8 @@ public class BubbleController { // Clear out any persisted bubbles on disk that no longer have a valid user. List<UserInfo> users = mUserManager.getAliveUsers(); mDataRepository.sanitizeBubbles(users); + + mShellController.addConfigurationChangeListener(this); } @VisibleForTesting @@ -798,7 +805,8 @@ public class BubbleController { mSavedBubbleKeysPerUser.remove(userId); } - private void updateForThemeChanges() { + @Override + public void onThemeChanged() { if (mStackView != null) { mStackView.onThemeChanged(); } @@ -818,7 +826,8 @@ public class BubbleController { } } - private void onConfigChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { if (mBubblePositioner != null) { mBubblePositioner.update(); } @@ -1678,13 +1687,6 @@ public class BubbleController { } @Override - public void updateForThemeChanges() { - mMainExecutor.execute(() -> { - BubbleController.this.updateForThemeChanges(); - }); - } - - @Override public void expandStackAndSelectBubble(BubbleEntry entry) { mMainExecutor.execute(() -> { BubbleController.this.expandStackAndSelectBubble(entry); @@ -1823,13 +1825,6 @@ public class BubbleController { } @Override - public void onConfigChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - BubbleController.this.onConfigChanged(newConfig); - }); - } - - @Override public void onNotificationPanelExpandedChanged(boolean expanded) { mMainExecutor.execute( () -> BubbleController.this.onNotificationPanelExpandedChanged(expanded)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 0072da19b9ef..f8ccf2364b4c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -107,9 +107,6 @@ public interface Bubbles { /** Tell the stack of bubbles to collapse. */ void collapseStack(); - /** Tell the controller need update its UI to fit theme. */ - void updateForThemeChanges(); - /** * Request the stack expand if needed, then select the specified Bubble as current. * If no bubble exists for this entry, one is created. @@ -255,13 +252,6 @@ public interface Bubbles { */ void onUserRemoved(int removedUserId); - /** - * Called when config changed. - * - * @param newConfig the new config. - */ - void onConfigChanged(Configuration newConfig); - /** Description of current bubble state. */ void dump(PrintWriter pw, String[] args); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index 6a2acf438302..b3f62477077c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.graphics.Point; @@ -324,7 +325,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } @Override - public void topFocusedWindowChanged(String packageName, + public void topFocusedWindowChanged(ComponentName component, InsetsVisibilities requestedVisibilities) { // Do nothing } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java index b6705446674a..f546f110e87c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java @@ -16,6 +16,7 @@ package com.android.wm.shell.common; +import android.content.ComponentName; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; @@ -171,14 +172,14 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan } } - private void topFocusedWindowChanged(String packageName, + private void topFocusedWindowChanged(ComponentName component, InsetsVisibilities requestedVisibilities) { CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId); if (listeners == null) { return; } for (OnInsetsChangedListener listener : listeners) { - listener.topFocusedWindowChanged(packageName, requestedVisibilities); + listener.topFocusedWindowChanged(component, requestedVisibilities); } } @@ -186,10 +187,10 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan private class DisplayWindowInsetsControllerImpl extends IDisplayWindowInsetsController.Stub { @Override - public void topFocusedWindowChanged(String packageName, + public void topFocusedWindowChanged(ComponentName component, InsetsVisibilities requestedVisibilities) throws RemoteException { mMainExecutor.execute(() -> { - PerDisplay.this.topFocusedWindowChanged(packageName, requestedVisibilities); + PerDisplay.this.topFocusedWindowChanged(component, requestedVisibilities); }); } @@ -234,10 +235,10 @@ public class DisplayInsetsController implements DisplayController.OnDisplaysChan /** * Called when top focused window changes to determine whether or not to take over insets * control. Won't be called if config_remoteInsetsControllerControlsSystemBars is false. - * @param packageName The name of the package that is open in the top focussed window. + * @param component The application component that is open in the top focussed window. * @param requestedVisibilities The insets visibilities requested by the focussed window. */ - default void topFocusedWindowChanged(String packageName, + default void topFocusedWindowChanged(ComponentName component, InsetsVisibilities requestedVisibilities) {} /** 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 b69cbfa83d7c..40cf9a32d7a5 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 @@ -727,31 +727,23 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange ActivityManager.RunningTaskInfo taskInfo1, ActivityManager.RunningTaskInfo taskInfo2) { if (offsetX == 0 && offsetY == 0) { wct.setBounds(taskInfo1.token, mBounds1); - wct.setAppBounds(taskInfo1.token, null); wct.setScreenSizeDp(taskInfo1.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); wct.setBounds(taskInfo2.token, mBounds2); - wct.setAppBounds(taskInfo2.token, null); wct.setScreenSizeDp(taskInfo2.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } else { - mTempRect.set(taskInfo1.configuration.windowConfiguration.getBounds()); + getBounds1(mTempRect); mTempRect.offset(offsetX, offsetY); wct.setBounds(taskInfo1.token, mTempRect); - mTempRect.set(taskInfo1.configuration.windowConfiguration.getAppBounds()); - mTempRect.offset(offsetX, offsetY); - wct.setAppBounds(taskInfo1.token, mTempRect); wct.setScreenSizeDp(taskInfo1.token, taskInfo1.configuration.screenWidthDp, taskInfo1.configuration.screenHeightDp); - mTempRect.set(taskInfo2.configuration.windowConfiguration.getBounds()); + getBounds2(mTempRect); mTempRect.offset(offsetX, offsetY); wct.setBounds(taskInfo2.token, mTempRect); - mTempRect.set(taskInfo2.configuration.windowConfiguration.getAppBounds()); - mTempRect.offset(offsetX, offsetY); - wct.setAppBounds(taskInfo2.token, mTempRect); wct.setScreenSizeDp(taskInfo2.token, taskInfo2.configuration.screenWidthDp, taskInfo2.configuration.screenHeightDp); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java index 99b32a677abe..db8d9d423aca 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java @@ -39,9 +39,10 @@ import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListen import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; -import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.compatui.CompatUIWindowManager.CompatUIHintsState; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import java.lang.ref.WeakReference; @@ -58,7 +59,7 @@ import dagger.Lazy; * activities are in compatibility mode. */ public class CompatUIController implements OnDisplaysChangedListener, - DisplayImeController.ImePositionProcessor { + DisplayImeController.ImePositionProcessor, KeyguardChangeListener { /** Callback for compat UI interaction. */ public interface CompatUICallback { @@ -100,13 +101,13 @@ public class CompatUIController implements OnDisplaysChangedListener, private final SparseArray<WeakReference<Context>> mDisplayContextCache = new SparseArray<>(0); private final Context mContext; + private final ShellController mShellController; private final DisplayController mDisplayController; private final DisplayInsetsController mDisplayInsetsController; private final DisplayImeController mImeController; private final SyncTransactionQueue mSyncQueue; private final ShellExecutor mMainExecutor; private final Lazy<Transitions> mTransitionsLazy; - private final CompatUIImpl mImpl = new CompatUIImpl(); private CompatUICallback mCallback; @@ -118,6 +119,7 @@ public class CompatUIController implements OnDisplaysChangedListener, private boolean mKeyguardShowing; public CompatUIController(Context context, + ShellController shellController, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, @@ -125,6 +127,7 @@ public class CompatUIController implements OnDisplaysChangedListener, ShellExecutor mainExecutor, Lazy<Transitions> transitionsLazy) { mContext = context; + mShellController = shellController; mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; mImeController = imeController; @@ -134,11 +137,7 @@ public class CompatUIController implements OnDisplaysChangedListener, mDisplayController.addDisplayWindowListener(this); mImeController.addPositionProcessor(this); mCompatUIHintsState = new CompatUIHintsState(); - } - - /** Returns implementation of {@link CompatUI}. */ - public CompatUI asCompatUI() { - return mImpl; + shellController.addKeyguardChangeListener(this); } /** Sets the callback for UI interactions. */ @@ -223,9 +222,10 @@ public class CompatUIController implements OnDisplaysChangedListener, layout -> layout.updateVisibility(showOnDisplay(displayId))); } - @VisibleForTesting - void onKeyguardShowingChanged(boolean showing) { - mKeyguardShowing = showing; + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + mKeyguardShowing = visible; // Hide the compat UIs when keyguard is showing. forAllLayouts(layout -> layout.updateVisibility(showOnDisplay(layout.getDisplayId()))); } @@ -373,19 +373,6 @@ public class CompatUIController implements OnDisplaysChangedListener, } } - /** - * The interface for calls from outside the Shell, within the host process. - */ - @ExternalThread - private class CompatUIImpl implements CompatUI { - @Override - public void onKeyguardShowingChanged(boolean showing) { - mMainExecutor.execute(() -> { - CompatUIController.this.onKeyguardShowingChanged(showing); - }); - } - } - /** An implementation of {@link OnInsetsChangedListener} for a given display id. */ private class PerDisplayOnInsetsChangedListener implements OnInsetsChangedListener { final int mDisplayId; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java index 1ea5e21a2c1e..81904e291ad1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java @@ -48,6 +48,7 @@ import com.android.wm.shell.pip.tv.TvPipNotificationController; import com.android.wm.shell.pip.tv.TvPipTaskOrganizer; import com.android.wm.shell.pip.tv.TvPipTransition; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import java.util.Optional; @@ -64,6 +65,7 @@ public abstract class TvPipModule { @Provides static Optional<Pip> providePip( Context context, + ShellController shellController, TvPipBoundsState tvPipBoundsState, TvPipBoundsAlgorithm tvPipBoundsAlgorithm, TvPipBoundsController tvPipBoundsController, @@ -81,6 +83,7 @@ public abstract class TvPipModule { return Optional.of( TvPipController.create( context, + shellController, tvPipBoundsState, tvPipBoundsAlgorithm, tvPipBoundsController, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index 2ea111b113d8..a168cb22f6ad 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -29,15 +29,12 @@ import com.android.internal.logging.UiEventLogger; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.RootDisplayAreaOrganizer; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; -import com.android.wm.shell.ShellCommandHandler; -import com.android.wm.shell.ShellCommandHandlerImpl; -import com.android.wm.shell.ShellInit; -import com.android.wm.shell.ShellInitImpl; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.TaskViewFactory; import com.android.wm.shell.TaskViewFactoryController; import com.android.wm.shell.TaskViewTransitions; import com.android.wm.shell.WindowManagerShellWrapper; +import com.android.wm.shell.activityembedding.ActivityEmbeddingController; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.back.BackAnimationController; import com.android.wm.shell.bubbles.BubbleController; @@ -56,15 +53,12 @@ import com.android.wm.shell.common.annotations.ShellAnimationThread; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.annotations.ShellSplashscreenThread; -import com.android.wm.shell.compatui.CompatUI; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.displayareahelper.DisplayAreaHelperController; -import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.draganddrop.DragAndDropController; -import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.fullscreen.FullscreenTaskListener; -import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController; import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer; import com.android.wm.shell.onehanded.OneHanded; @@ -82,8 +76,10 @@ import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.startingsurface.StartingWindowController; import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm; import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm; -import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper; -import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController; +import com.android.wm.shell.sysui.ShellCommandHandler; +import com.android.wm.shell.sysui.ShellController; +import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.sysui.ShellInterface; import com.android.wm.shell.transition.ShellTransitions; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; @@ -159,16 +155,13 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides static DragAndDropController provideDragAndDropController(Context context, - DisplayController displayController, UiEventLogger uiEventLogger, - IconProvider iconProvider, @ShellMainThread ShellExecutor mainExecutor) { - return new DragAndDropController(context, displayController, uiEventLogger, iconProvider, - mainExecutor); - } - - @WMSingleton - @Provides - static Optional<DragAndDrop> provideDragAndDrop(DragAndDropController dragAndDropController) { - return Optional.of(dragAndDropController.asDragAndDrop()); + ShellController shellController, + DisplayController displayController, + UiEventLogger uiEventLogger, + IconProvider iconProvider, + @ShellMainThread ShellExecutor mainExecutor) { + return new DragAndDropController(context, shellController, displayController, uiEventLogger, + iconProvider, mainExecutor); } @WMSingleton @@ -201,18 +194,14 @@ public abstract class WMShellBaseModule { } @WMSingleton - @Provides static Optional<CompatUI> provideCompatUI(CompatUIController compatUIController) { - return Optional.of(compatUIController.asCompatUI()); - } - - @WMSingleton @Provides static CompatUIController provideCompatUIController(Context context, + ShellController shellController, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue, @ShellMainThread ShellExecutor mainExecutor, Lazy<Transitions> transitionsLazy) { - return new CompatUIController(context, displayController, displayInsetsController, - imeController, syncQueue, mainExecutor, transitionsLazy); + return new CompatUIController(context, shellController, displayController, + displayInsetsController, imeController, syncQueue, mainExecutor, transitionsLazy); } @WMSingleton @@ -350,15 +339,15 @@ public abstract class WMShellBaseModule { // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride} @BindsOptionalOf @DynamicOverride - abstract FreeformTaskListener<?> optionalFreeformTaskListener(); + abstract FreeformComponents optionalFreeformComponents(); @WMSingleton @Provides - static Optional<FreeformTaskListener<?>> provideFreeformTaskListener( - @DynamicOverride Optional<FreeformTaskListener<?>> freeformTaskListener, + static Optional<FreeformComponents> provideFreeformTaskListener( + @DynamicOverride Optional<FreeformComponents> freeformComponents, Context context) { - if (FreeformTaskListener.isFreeformEnabled(context)) { - return freeformTaskListener; + if (FreeformComponents.isFreeformEnabled(context)) { + return freeformComponents; } return Optional.empty(); } @@ -369,17 +358,12 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static Optional<HideDisplayCutout> provideHideDisplayCutout( - Optional<HideDisplayCutoutController> hideDisplayCutoutController) { - return hideDisplayCutoutController.map((controller) -> controller.asHideDisplayCutout()); - } - - @WMSingleton - @Provides static Optional<HideDisplayCutoutController> provideHideDisplayCutoutController(Context context, - DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor) { + ShellController shellController, DisplayController displayController, + @ShellMainThread ShellExecutor mainExecutor) { return Optional.ofNullable( - HideDisplayCutoutController.create(context, displayController, mainExecutor)); + HideDisplayCutoutController.create(context, shellController, displayController, + mainExecutor)); } // @@ -408,23 +392,6 @@ public abstract class WMShellBaseModule { } // - // Task to Surface communication - // - - @WMSingleton - @Provides - static Optional<TaskSurfaceHelper> provideTaskSurfaceHelper( - Optional<TaskSurfaceHelperController> taskSurfaceController) { - return taskSurfaceController.map((controller) -> controller.asTaskSurfaceHelper()); - } - - @Provides - static Optional<TaskSurfaceHelperController> provideTaskSurfaceHelperController( - ShellTaskOrganizer taskOrganizer, @ShellMainThread ShellExecutor mainExecutor) { - return Optional.ofNullable(new TaskSurfaceHelperController(taskOrganizer, mainExecutor)); - } - - // // Pip (optional feature) // @@ -444,8 +411,8 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper() { - return new PipSurfaceTransactionHelper(); + static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) { + return new PipSurfaceTransactionHelper(context); } @WMSingleton @@ -621,19 +588,43 @@ public abstract class WMShellBaseModule { taskViewTransitions); } + // - // Misc + // ActivityEmbedding + // + + @WMSingleton + @Provides + static Optional<ActivityEmbeddingController> provideActivityEmbeddingController( + Context context, Transitions transitions) { + return Optional.of(new ActivityEmbeddingController(context, transitions)); + } + + // + // SysUI -> Shell interface // @WMSingleton @Provides - static ShellInit provideShellInit(ShellInitImpl impl) { - return impl.asShellInit(); + static ShellInterface provideShellSysuiCallbacks(ShellController shellController) { + return shellController.asShell(); } @WMSingleton @Provides - static ShellInitImpl provideShellInitImpl(DisplayController displayController, + static ShellController provideShellController(@ShellMainThread ShellExecutor mainExecutor) { + return new ShellController(mainExecutor); + } + + // + // Misc + // + + @WMSingleton + @Provides + static ShellInit provideShellInitImpl( + ShellController shellController, + DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, DragAndDropController dragAndDropController, @@ -645,12 +636,14 @@ public abstract class WMShellBaseModule { FullscreenTaskListener fullscreenTaskListener, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<UnfoldTransitionHandler> unfoldTransitionHandler, - Optional<FreeformTaskListener<?>> freeformTaskListener, + Optional<FreeformComponents> freeformComponents, Optional<RecentTasksController> recentTasksOptional, + Optional<ActivityEmbeddingController> activityEmbeddingOptional, Transitions transitions, StartingWindowController startingWindow, @ShellMainThread ShellExecutor mainExecutor) { - return new ShellInitImpl(displayController, + return new ShellInit(shellController, + displayController, displayImeController, displayInsetsController, dragAndDropController, @@ -662,26 +655,18 @@ public abstract class WMShellBaseModule { fullscreenTaskListener, unfoldAnimationController, unfoldTransitionHandler, - freeformTaskListener, + freeformComponents, recentTasksOptional, + activityEmbeddingOptional, transitions, startingWindow, mainExecutor); } - /** - * Note, this is only optional because we currently pass this to the SysUI component scope and - * for non-primary users, we may inject a null-optional for that dependency. - */ - @WMSingleton - @Provides - static Optional<ShellCommandHandler> provideShellCommandHandler(ShellCommandHandlerImpl impl) { - return Optional.of(impl.asShellCommandHandler()); - } - @WMSingleton @Provides - static ShellCommandHandlerImpl provideShellCommandHandlerImpl( + static ShellCommandHandler provideShellCommandHandlerImpl( + ShellController shellController, ShellTaskOrganizer shellTaskOrganizer, KidsModeTaskOrganizer kidsModeTaskOrganizer, Optional<SplitScreenController> splitScreenOptional, @@ -690,9 +675,9 @@ public abstract class WMShellBaseModule { Optional<HideDisplayCutoutController> hideDisplayCutout, Optional<RecentTasksController> recentTasksOptional, @ShellMainThread ShellExecutor mainExecutor) { - return new ShellCommandHandlerImpl(shellTaskOrganizer, kidsModeTaskOrganizer, - splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout, - recentTasksOptional, mainExecutor); + return new ShellCommandHandler(shellController, shellTaskOrganizer, + kidsModeTaskOrganizer, splitScreenOptional, pipOptional, oneHandedOptional, + hideDisplayCutout, recentTasksOptional, mainExecutor); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java index cc741d3896a2..35a309a8352c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellConcurrencyModule.java @@ -27,6 +27,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Trace; +import android.view.Choreographer; import androidx.annotation.Nullable; @@ -144,6 +145,25 @@ public abstract class WMShellConcurrencyModule { } /** + * Provide a Shell main-thread {@link Choreographer} with the app vsync. + * + * @param executor the executor of the shell main thread + */ + @WMSingleton + @Provides + @ShellMainThread + public static Choreographer provideShellMainChoreographer( + @ShellMainThread ShellExecutor executor) { + try { + final Choreographer[] choreographer = new Choreographer[1]; + executor.executeBlocking(() -> choreographer[0] = Choreographer.getInstance()); + return choreographer[0]; + } catch (InterruptedException e) { + throw new RuntimeException("Failed to obtain main Choreographer.", e); + } + } + + /** * Provide a Shell animation-thread Executor. */ @WMSingleton 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 189743728840..588a1aa57a3a 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 @@ -20,6 +20,7 @@ import android.content.Context; import android.content.pm.LauncherApps; import android.os.Handler; import android.os.UserManager; +import android.view.Choreographer; import android.view.WindowManager; import com.android.internal.jank.InteractionJankMonitor; @@ -48,7 +49,9 @@ import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.draganddrop.DragAndDropController; +import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.freeform.FreeformTaskTransitionHandler; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipAnimationController; @@ -71,6 +74,7 @@ import com.android.wm.shell.pip.phone.PipMotionHelper; 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.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.UnfoldAnimationController; @@ -134,6 +138,7 @@ public abstract class WMShellModule { @WMSingleton @Provides static BubbleController provideBubbleController(Context context, + ShellController shellController, BubbleData data, FloatingContentCoordinator floatingContentCoordinator, IStatusBarService statusBarService, @@ -153,7 +158,7 @@ public abstract class WMShellModule { @ShellBackgroundThread ShellExecutor bgExecutor, TaskViewTransitions taskViewTransitions, SyncTransactionQueue syncQueue) { - return new BubbleController(context, data, null /* synchronizer */, + return new BubbleController(context, shellController, data, null /* synchronizer */, floatingContentCoordinator, new BubbleDataRepository(context, launcherApps, mainExecutor), statusBarService, windowManager, windowManagerShellWrapper, userManager, @@ -171,12 +176,14 @@ public abstract class WMShellModule { static WindowDecorViewModel<?> provideWindowDecorViewModel( Context context, @ShellMainThread Handler mainHandler, + @ShellMainThread Choreographer mainChoreographer, ShellTaskOrganizer taskOrganizer, DisplayController displayController, SyncTransactionQueue syncQueue) { return new CaptionWindowDecorViewModel( context, mainHandler, + mainChoreographer, taskOrganizer, displayController, syncQueue); @@ -189,10 +196,27 @@ public abstract class WMShellModule { @WMSingleton @Provides @DynamicOverride + static FreeformComponents provideFreeformComponents( + FreeformTaskListener<?> taskListener, + FreeformTaskTransitionHandler transitionHandler) { + return new FreeformComponents(taskListener, Optional.of(transitionHandler)); + } + + @WMSingleton + @Provides static FreeformTaskListener<?> provideFreeformTaskListener( + WindowDecorViewModel<?> windowDecorViewModel) { + return new FreeformTaskListener<>(windowDecorViewModel); + } + + @WMSingleton + @Provides + static FreeformTaskTransitionHandler provideTaskTransitionHandler( + Transitions transitions, WindowDecorViewModel<?> windowDecorViewModel, - SyncTransactionQueue syncQueue) { - return new FreeformTaskListener<>(windowDecorViewModel, syncQueue); + FreeformTaskListener<?> freeformTaskListener) { + return new FreeformTaskTransitionHandler(transitions, windowDecorViewModel, + freeformTaskListener); } // @@ -205,12 +229,14 @@ public abstract class WMShellModule { @Provides @DynamicOverride static OneHandedController provideOneHandedController(Context context, + ShellController shellController, WindowManager windowManager, DisplayController displayController, DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener, UiEventLogger uiEventLogger, InteractionJankMonitor jankMonitor, @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) { - return OneHandedController.create(context, windowManager, displayController, displayLayout, - taskStackListener, jankMonitor, uiEventLogger, mainExecutor, mainHandler); + return OneHandedController.create(context, shellController, windowManager, + displayController, displayLayout, taskStackListener, jankMonitor, uiEventLogger, + mainExecutor, mainHandler); } // @@ -221,6 +247,7 @@ public abstract class WMShellModule { @Provides @DynamicOverride static SplitScreenController provideSplitScreenController( + ShellController shellController, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, Context context, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, @@ -230,7 +257,7 @@ public abstract class WMShellModule { DisplayInsetsController displayInsetsController, Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider, Optional<RecentTasksController> recentTasks) { - return new SplitScreenController(shellTaskOrganizer, syncQueue, context, + return new SplitScreenController(shellController, shellTaskOrganizer, syncQueue, context, rootTaskDisplayAreaOrganizer, mainExecutor, displayController, displayImeController, displayInsetsController, transitions, transactionPool, iconProvider, recentTasks); @@ -242,7 +269,8 @@ public abstract class WMShellModule { @WMSingleton @Provides - static Optional<Pip> providePip(Context context, DisplayController displayController, + static Optional<Pip> providePip(Context context, + ShellController shellController, DisplayController displayController, PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm, PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState, PipMotionHelper pipMotionHelper, PipMediaController pipMediaController, @@ -254,7 +282,7 @@ public abstract class WMShellModule { PipParamsChangedForwarder pipParamsChangedForwarder, Optional<OneHandedController> oneHandedController, @ShellMainThread ShellExecutor mainExecutor) { - return Optional.ofNullable(PipController.create(context, displayController, + return Optional.ofNullable(PipController.create(context, shellController, displayController, pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/sysui.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/sysui.md index 68f970ff48df..0dd50b1bee68 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/sysui.md +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/sysui.md @@ -52,4 +52,14 @@ For example, you might have: call, and the callback posts to the main SysUI thread Adding an interface to a Shell component may seem like a lot of boiler plate, but is currently -necessary to maintain proper threading and logic isolation.
\ No newline at end of file +necessary to maintain proper threading and logic isolation. + +## Configuration changes & other SysUI events + +Aside from direct calls into Shell controllers for exposed features, the Shell also receives +common event callbacks from SysUI via the `ShellController`. This includes things like: + +- Configuration changes +- TODO: Shell init +- TODO: Shell command +- TODO: Keyguard events
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java deleted file mode 100644 index edeff6e37182..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.draganddrop; - -import android.content.res.Configuration; - -import com.android.wm.shell.common.annotations.ExternalThread; - -/** - * Interface for telling DragAndDrop stuff. - */ -@ExternalThread -public interface DragAndDrop { - - /** Called when the theme changes. */ - void onThemeChanged(); - - /** Called when the configuration changes. */ - void onConfigChanged(Configuration newConfig); -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 95de2dc61a43..c5df53b6dbc8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -60,6 +60,8 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.ShellController; import java.util.ArrayList; import java.util.Optional; @@ -68,21 +70,20 @@ import java.util.Optional; * Handles the global drag and drop handling for the Shell. */ public class DragAndDropController implements DisplayController.OnDisplaysChangedListener, - View.OnDragListener { + View.OnDragListener, ConfigurationChangeListener { private static final String TAG = DragAndDropController.class.getSimpleName(); private final Context mContext; + private final ShellController mShellController; private final DisplayController mDisplayController; private final DragAndDropEventLogger mLogger; private final IconProvider mIconProvider; private SplitScreenController mSplitScreen; private ShellExecutor mMainExecutor; - private DragAndDropImpl mImpl; private ArrayList<DragAndDropListener> mListeners = new ArrayList<>(); private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>(); - private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); /** * Listener called during drag events, currently just onDragStarted. @@ -92,23 +93,24 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange void onDragStarted(); } - public DragAndDropController(Context context, DisplayController displayController, - UiEventLogger uiEventLogger, IconProvider iconProvider, ShellExecutor mainExecutor) { + public DragAndDropController(Context context, + ShellController shellController, + DisplayController displayController, + UiEventLogger uiEventLogger, + IconProvider iconProvider, + ShellExecutor mainExecutor) { mContext = context; + mShellController = shellController; mDisplayController = displayController; mLogger = new DragAndDropEventLogger(uiEventLogger); mIconProvider = iconProvider; mMainExecutor = mainExecutor; - mImpl = new DragAndDropImpl(); - } - - public DragAndDrop asDragAndDrop() { - return mImpl; } public void initialize(Optional<SplitScreenController> splitscreen) { mSplitScreen = splitscreen.orElse(null); mDisplayController.addDisplayWindowListener(this); + mShellController.addConfigurationChangeListener(this); } /** Adds a listener to be notified of drag and drop events. */ @@ -310,13 +312,15 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange return mimeTypes; } - private void onThemeChange() { + @Override + public void onThemeChanged() { for (int i = 0; i < mDisplayDropTargets.size(); i++) { mDisplayDropTargets.get(i).dragLayout.onThemeChange(); } } - private void onConfigChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { for (int i = 0; i < mDisplayDropTargets.size(); i++) { mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig); } @@ -342,21 +346,4 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange dragLayout = dl; } } - - private class DragAndDropImpl implements DragAndDrop { - - @Override - public void onThemeChanged() { - mMainExecutor.execute(() -> { - DragAndDropController.this.onThemeChange(); - }); - } - - @Override - public void onConfigChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - DragAndDropController.this.onConfigChanged(newConfig); - }); - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java new file mode 100644 index 000000000000..41e1b1de2546 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java @@ -0,0 +1,56 @@ +/* + * 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.wm.shell.freeform; + +import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; +import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; + +import android.content.Context; +import android.provider.Settings; + +import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.transition.Transitions; + +import java.util.Optional; + +/** + * Class that holds freeform related classes. It serves as the single injection point of + * all freeform classes to avoid leaking implementation details to the base Dagger module. + */ +public class FreeformComponents { + public final ShellTaskOrganizer.TaskListener mTaskListener; + public final Optional<Transitions.TransitionHandler> mTaskTransitionHandler; + + /** + * Creates an instance with the given components. + */ + public FreeformComponents( + ShellTaskOrganizer.TaskListener taskListener, + Optional<Transitions.TransitionHandler> taskTransitionHandler) { + mTaskListener = taskListener; + mTaskTransitionHandler = taskTransitionHandler; + } + + /** + * Returns if this device supports freeform. + */ + public static boolean isFreeformEnabled(Context context) { + return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT) + || Settings.Global.getInt(context.getContentResolver(), + DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0; + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index 692e6acb540c..ba093a5fcc05 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -16,20 +16,18 @@ package com.android.wm.shell.freeform; -import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; -import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; - import android.app.ActivityManager.RunningTaskInfo; -import android.content.Context; -import android.provider.Settings; -import android.util.Slog; +import android.util.Log; import android.util.SparseArray; import android.view.SurfaceControl; +import android.window.TransitionInfo; + +import androidx.annotation.Nullable; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import java.io.PrintWriter; @@ -45,9 +43,9 @@ public class FreeformTaskListener<T extends AutoCloseable> private static final String TAG = "FreeformTaskListener"; private final WindowDecorViewModel<T> mWindowDecorationViewModel; - private final SyncTransactionQueue mSyncQueue; private final SparseArray<State<T>> mTasks = new SparseArray<>(); + private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>(); private static class State<T extends AutoCloseable> { RunningTaskInfo mTaskInfo; @@ -55,57 +53,78 @@ public class FreeformTaskListener<T extends AutoCloseable> T mWindowDecoration; } - public FreeformTaskListener( - WindowDecorViewModel<T> windowDecorationViewModel, - SyncTransactionQueue syncQueue) { + public FreeformTaskListener(WindowDecorViewModel<T> windowDecorationViewModel) { mWindowDecorationViewModel = windowDecorationViewModel; - mSyncQueue = syncQueue; } @Override public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { - if (mTasks.get(taskInfo.taskId) != null) { - throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId); - } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d", taskInfo.taskId); - final State<T> state = new State<>(); + final State<T> state = createOrUpdateTaskState(taskInfo, leash); + if (!Transitions.ENABLE_SHELL_TRANSITIONS) { + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + state.mWindowDecoration = + mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t); + t.apply(); + } + } + + private State<T> createOrUpdateTaskState(RunningTaskInfo taskInfo, SurfaceControl leash) { + State<T> state = mTasks.get(taskInfo.taskId); + if (state != null) { + updateTaskInfo(taskInfo); + return state; + } + + state = new State<>(); state.mTaskInfo = taskInfo; state.mLeash = leash; - state.mWindowDecoration = - mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash); mTasks.put(taskInfo.taskId, state); + + return state; } @Override public void onTaskVanished(RunningTaskInfo taskInfo) { - State<T> state = mTasks.get(taskInfo.taskId); + final State<T> state = mTasks.get(taskInfo.taskId); if (state == null) { - Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); + // This is possible if the transition happens before this method. return; } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d", taskInfo.taskId); mTasks.remove(taskInfo.taskId); - try { - state.mWindowDecoration.close(); - } catch (Exception e) { - Slog.e(TAG, "Failed to release window decoration.", e); + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + // Save window decorations of closing tasks so that we can hand them over to the + // transition system if this method happens before the transition. In case where the + // transition didn't happen, it'd be cleared when the next transition finished. + if (state.mWindowDecoration != null) { + mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration); + } + return; } + releaseWindowDecor(state.mWindowDecoration); } @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { - State<T> state = mTasks.get(taskInfo.taskId); - if (state == null) { - throw new RuntimeException( - "Task info changed before appearing: #" + taskInfo.taskId); - } + final State<T> state = updateTaskInfo(taskInfo); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d", taskInfo.taskId); + if (state.mWindowDecoration != null) { + mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration); + } + } + + private State<T> updateTaskInfo(RunningTaskInfo taskInfo) { + final State<T> state = mTasks.get(taskInfo.taskId); + if (state == null) { + throw new RuntimeException("Task info changed before appearing: #" + taskInfo.taskId); + } state.mTaskInfo = taskInfo; - mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration); + return state; } @Override @@ -126,6 +145,93 @@ public class FreeformTaskListener<T extends AutoCloseable> return mTasks.get(taskId).mLeash; } + /** + * Creates a window decoration for a transition. + * + * @param change the change of this task transition that needs to have the task layer as the + * leash + * @return {@code true} if it adopts the window decoration; {@code false} otherwise + */ + void createWindowDecoration( + TransitionInfo.Change change, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); + state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration( + state.mTaskInfo, state.mLeash, startT, finishT); + } + + /** + * Gives out the ownership of the task's window decoration. The given task is leaving (of has + * left) this task listener. This is the transition system asking for the ownership. + * + * @param taskInfo the maximizing task + * @return the window decor of the maximizing task if any + */ + T giveWindowDecoration( + RunningTaskInfo taskInfo, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + T windowDecor = mWindowDecorOfVanishedTasks.get(taskInfo.taskId); + mWindowDecorOfVanishedTasks.remove(taskInfo.taskId); + final State<T> state = mTasks.get(taskInfo.taskId); + if (state != null) { + windowDecor = windowDecor == null ? state.mWindowDecoration : windowDecor; + state.mWindowDecoration = null; + } + mWindowDecorationViewModel.setupWindowDecorationForTransition( + taskInfo, startT, finishT, windowDecor); + return windowDecor; + } + + /** + * Adopt the incoming window decoration and lets the window decoration prepare for a transition. + * + * @param change the change of this task transition that needs to have the task layer as the + * leash + * @param startT the start transaction of this transition + * @param finishT the finish transaction of this transition + * @param windowDecor the window decoration to adopt + * @return {@code true} if it adopts the window decoration; {@code false} otherwise + */ + boolean adoptWindowDecoration( + TransitionInfo.Change change, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT, + @Nullable AutoCloseable windowDecor) { + final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); + state.mWindowDecoration = mWindowDecorationViewModel.adoptWindowDecoration(windowDecor); + if (state.mWindowDecoration != null) { + mWindowDecorationViewModel.setupWindowDecorationForTransition( + state.mTaskInfo, startT, finishT, state.mWindowDecoration); + return true; + } else { + state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration( + state.mTaskInfo, state.mLeash, startT, finishT); + return false; + } + } + + void onTaskTransitionFinished() { + if (mWindowDecorOfVanishedTasks.size() == 0) { + return; + } + Log.w(TAG, "Clearing window decors of vanished tasks. There could be visual defects " + + "if any of them is used later in transitions."); + for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) { + releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i)); + } + mWindowDecorOfVanishedTasks.clear(); + } + + private void releaseWindowDecor(T windowDecor) { + try { + windowDecor.close(); + } catch (Exception e) { + Log.e(TAG, "Failed to release window decoration.", e); + } + } + @Override public void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; @@ -137,16 +243,4 @@ public class FreeformTaskListener<T extends AutoCloseable> public String toString() { return TAG; } - - /** - * Checks if freeform support is enabled in system. - * - * @param context context used to check settings and package manager. - * @return {@code true} if freeform is enabled, {@code false} if not. - */ - public static boolean isFreeformEnabled(Context context) { - return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT) - || Settings.Global.getInt(context.getContentResolver(), - DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0; - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java new file mode 100644 index 000000000000..8731eb604cbc --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java @@ -0,0 +1,234 @@ +/* + * 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.wm.shell.freeform; + +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; + +import android.app.ActivityManager; +import android.app.WindowConfiguration; +import android.os.IBinder; +import android.util.Log; +import android.view.SurfaceControl; +import android.view.WindowManager; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; +import android.window.WindowContainerTransaction; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.wm.shell.transition.Transitions; +import com.android.wm.shell.windowdecor.WindowDecorViewModel; + +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link Transitions.TransitionHandler} that handles freeform task launches, closes, + * maximizing and restoring transitions. It also reports transitions so that window decorations can + * be a part of transitions. + */ +public class FreeformTaskTransitionHandler + implements Transitions.TransitionHandler, FreeformTaskTransitionStarter { + private static final String TAG = "FreeformTH"; + + private final Transitions mTransitions; + private final FreeformTaskListener<?> mFreeformTaskListener; + + private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); + + public FreeformTaskTransitionHandler( + Transitions transitions, + WindowDecorViewModel<?> windowDecorViewModel, + FreeformTaskListener<?> freeformTaskListener) { + mTransitions = transitions; + mFreeformTaskListener = freeformTaskListener; + + windowDecorViewModel.setFreeformTaskTransitionStarter(this); + } + + @Override + public void startWindowingModeTransition( + int targetWindowingMode, WindowContainerTransaction wct) { + final int type; + switch (targetWindowingMode) { + case WINDOWING_MODE_FULLSCREEN: + type = Transitions.TRANSIT_MAXIMIZE; + break; + case WINDOWING_MODE_FREEFORM: + type = Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE; + break; + default: + throw new IllegalArgumentException("Unexpected target windowing mode " + + WindowConfiguration.windowingModeToString(targetWindowingMode)); + } + final IBinder token = mTransitions.startTransition(type, wct, this); + mPendingTransitionTokens.add(token); + } + + @Override + public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startT, + @NonNull SurfaceControl.Transaction finishT, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + boolean transitionHandled = false; + final ArrayList<AutoCloseable> windowDecorsInCloseTransitions = new ArrayList<>(); + for (TransitionInfo.Change change : info.getChanges()) { + if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { + continue; + } + + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (taskInfo == null || taskInfo.taskId == -1) { + continue; + } + + switch (change.getMode()) { + case WindowManager.TRANSIT_OPEN: + transitionHandled |= startOpenTransition(change, startT, finishT); + break; + case WindowManager.TRANSIT_CLOSE: + transitionHandled |= startCloseTransition( + change, windowDecorsInCloseTransitions, startT, finishT); + break; + case WindowManager.TRANSIT_CHANGE: + transitionHandled |= startChangeTransition( + transition, info.getType(), change, startT, finishT); + break; + case WindowManager.TRANSIT_TO_BACK: + case WindowManager.TRANSIT_TO_FRONT: + transitionHandled = true; + break; + } + } + + mPendingTransitionTokens.remove(transition); + + if (!transitionHandled) { + return false; + } + + startT.apply(); + mTransitions.getMainExecutor().execute( + () -> finishTransition(windowDecorsInCloseTransitions, finishCallback)); + return true; + } + + private boolean startOpenTransition( + TransitionInfo.Change change, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) { + return false; + } + mFreeformTaskListener.createWindowDecoration(change, startT, finishT); + return true; + } + + private boolean startCloseTransition( + TransitionInfo.Change change, + ArrayList<AutoCloseable> windowDecors, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) { + return false; + } + final AutoCloseable windowDecor = + mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(), startT, finishT); + if (windowDecor != null) { + windowDecors.add(windowDecor); + } + + return true; + } + + private boolean startChangeTransition( + IBinder transition, + int type, + TransitionInfo.Change change, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + AutoCloseable windowDecor = null; + + if (!mPendingTransitionTokens.contains(transition)) { + return false; + } + + boolean handled = false; + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (type == Transitions.TRANSIT_MAXIMIZE + && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + handled = true; + windowDecor = mFreeformTaskListener.giveWindowDecoration( + change.getTaskInfo(), startT, finishT); + // TODO(b/235638450): Let fullscreen task listener adopt the window decor. + } + + if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE + && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) { + handled = true; + // TODO(b/235638450): Let fullscreen task listener transfer the window decor. + mFreeformTaskListener.adoptWindowDecoration(change, startT, finishT, windowDecor); + } + + releaseWindowDecor(windowDecor); + + return handled; + } + + private void finishTransition( + ArrayList<AutoCloseable> windowDecorsInCloseTransitions, + Transitions.TransitionFinishCallback finishCallback) { + for (AutoCloseable windowDecor : windowDecorsInCloseTransitions) { + releaseWindowDecor(windowDecor); + } + mFreeformTaskListener.onTaskTransitionFinished(); + // TODO(b/235638450): Dispatch it to fullscreen task listener. + finishCallback.onTransitionFinished(null, null); + } + + private void releaseWindowDecor(AutoCloseable windowDecor) { + if (windowDecor == null) { + return; + } + try { + windowDecor.close(); + } catch (Exception e) { + Log.e(TAG, "Failed to release window decoration.", e); + } + } + + @Nullable + @Override + public WindowContainerTransaction handleRequest(@NonNull IBinder transition, + @NonNull TransitionRequestInfo request) { + final ActivityManager.RunningTaskInfo taskInfo = request.getTriggerTask(); + if (taskInfo == null || taskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) { + return null; + } + switch (request.getType()) { + case WindowManager.TRANSIT_OPEN: + case WindowManager.TRANSIT_CLOSE: + case WindowManager.TRANSIT_TO_FRONT: + case WindowManager.TRANSIT_TO_BACK: + return new WindowContainerTransaction(); + default: + return null; + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUI.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java index b87cf47dd93f..25eaa0e05a09 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUI.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * 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. @@ -14,22 +14,21 @@ * limitations under the License. */ -package com.android.wm.shell.compatui; +package com.android.wm.shell.freeform; -import com.android.wm.shell.common.annotations.ExternalThread; +import android.window.WindowContainerTransaction; /** - * Interface to engage compat UI. + * The interface around {@link FreeformTaskTransitionHandler} for task listeners to start freeform + * task transitions. */ -@ExternalThread -public interface CompatUI { +public interface FreeformTaskTransitionStarter { + /** - * Called when the keyguard showing state changes. Removes all compat UIs if the - * keyguard is now showing. - * - * <p>Note that if the keyguard is occluded it will also be considered showing. + * Starts a windowing mode transition. * - * @param showing indicates if the keyguard is now showing. + * @param targetWindowingMode the target windowing mode + * @param wct the {@link WindowContainerTransaction} that changes the windowing mode */ - void onKeyguardShowingChanged(boolean showing); + void startWindowingModeTransition(int targetWindowingMode, WindowContainerTransaction wct); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutout.java deleted file mode 100644 index 60123ab97fd7..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutout.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.hidedisplaycutout; - -import android.content.res.Configuration; - -import androidx.annotation.NonNull; - -import com.android.wm.shell.common.annotations.ExternalThread; - -import java.io.PrintWriter; - -/** - * Interface to engage hide display cutout feature. - */ -@ExternalThread -public interface HideDisplayCutout { - /** - * Notifies {@link Configuration} changed. - */ - void onConfigurationChanged(Configuration newConfig); -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java index 23f76ca5f6ae..665b035bc41c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java @@ -19,7 +19,6 @@ package com.android.wm.shell.hidedisplaycutout; import android.content.Context; import android.content.res.Configuration; import android.os.SystemProperties; -import android.util.Slog; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -27,20 +26,20 @@ import androidx.annotation.VisibleForTesting; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.ShellController; import java.io.PrintWriter; -import java.util.concurrent.TimeUnit; /** * Manages the hide display cutout status. */ -public class HideDisplayCutoutController { +public class HideDisplayCutoutController implements ConfigurationChangeListener { private static final String TAG = "HideDisplayCutoutController"; private final Context mContext; + private final ShellController mShellController; private final HideDisplayCutoutOrganizer mOrganizer; - private final ShellExecutor mMainExecutor; - private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl(); @VisibleForTesting boolean mEnabled; @@ -49,8 +48,9 @@ public class HideDisplayCutoutController { * supported. */ @Nullable - public static HideDisplayCutoutController create( - Context context, DisplayController displayController, ShellExecutor mainExecutor) { + public static HideDisplayCutoutController create(Context context, + ShellController shellController, DisplayController displayController, + ShellExecutor mainExecutor) { // The SystemProperty is set for devices that support this feature and is used to control // whether to create the HideDisplayCutout instance. // It's defined in the device.mk (e.g. device/google/crosshatch/device.mk). @@ -60,19 +60,16 @@ public class HideDisplayCutoutController { HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer(context, displayController, mainExecutor); - return new HideDisplayCutoutController(context, organizer, mainExecutor); + return new HideDisplayCutoutController(context, shellController, organizer); } - HideDisplayCutoutController(Context context, HideDisplayCutoutOrganizer organizer, - ShellExecutor mainExecutor) { + HideDisplayCutoutController(Context context, ShellController shellController, + HideDisplayCutoutOrganizer organizer) { mContext = context; + mShellController = shellController; mOrganizer = organizer; - mMainExecutor = mainExecutor; updateStatus(); - } - - public HideDisplayCutout asHideDisplayCutout() { - return mImpl; + mShellController.addConfigurationChangeListener(this); } @VisibleForTesting @@ -94,7 +91,8 @@ public class HideDisplayCutoutController { } } - private void onConfigurationChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { updateStatus(); } @@ -107,13 +105,4 @@ public class HideDisplayCutoutController { pw.println(mEnabled); mOrganizer.dump(pw); } - - private class HideDisplayCutoutImpl implements HideDisplayCutout { - @Override - public void onConfigurationChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - HideDisplayCutoutController.this.onConfigurationChanged(newConfig); - }); - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java index 9478b347653f..f376e1fd6174 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java @@ -64,8 +64,8 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { @VisibleForTesting final Rect mCurrentDisplayBounds = new Rect(); // The default display cutout in natural orientation. - private Insets mDefaultCutoutInsets; - private Insets mCurrentCutoutInsets; + private Insets mDefaultCutoutInsets = Insets.NONE; + private Insets mCurrentCutoutInsets = Insets.NONE; private boolean mIsDefaultPortrait; private int mStatusBarHeight; @VisibleForTesting @@ -78,27 +78,35 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { private final DisplayController.OnDisplaysChangedListener mListener = new DisplayController.OnDisplaysChangedListener() { @Override + public void onDisplayAdded(int displayId) { + onDisplayChanged(displayId); + } + + @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { - if (displayId != DEFAULT_DISPLAY) { - return; - } - DisplayLayout displayLayout = - mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); - if (displayLayout == null) { - return; - } - final boolean rotationChanged = mRotation != displayLayout.rotation(); - mRotation = displayLayout.rotation(); - if (rotationChanged || isDisplayBoundsChanged()) { - updateBoundsAndOffsets(true /* enabled */); - final WindowContainerTransaction wct = new WindowContainerTransaction(); - final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - applyAllBoundsAndOffsets(wct, t); - applyTransaction(wct, t); - } + onDisplayChanged(displayId); } }; + private void onDisplayChanged(int displayId) { + if (displayId != DEFAULT_DISPLAY) { + return; + } + final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); + if (displayLayout == null) { + return; + } + final boolean rotationChanged = mRotation != displayLayout.rotation(); + mRotation = displayLayout.rotation(); + if (rotationChanged || isDisplayBoundsChanged()) { + updateBoundsAndOffsets(true /* enabled */); + final WindowContainerTransaction wct = new WindowContainerTransaction(); + final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + applyAllBoundsAndOffsets(wct, t); + applyTransaction(wct, t); + } + } + HideDisplayCutoutOrganizer(Context context, DisplayController displayController, ShellExecutor mainExecutor) { super(mainExecutor); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java index b00182f36cc8..76c0f41997ad 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java @@ -16,7 +16,6 @@ package com.android.wm.shell.onehanded; -import android.content.res.Configuration; import android.os.SystemProperties; import com.android.wm.shell.common.annotations.ExternalThread; @@ -83,17 +82,7 @@ public interface OneHanded { void registerTransitionCallback(OneHandedTransitionCallback callback); /** - * Receive onConfigurationChanged() events - */ - void onConfigChanged(Configuration newConfig); - - /** * Notifies when user switch complete */ void onUserSwitch(int userId); - - /** - * Notifies when keyguard visibility changed - */ - void onKeyguardVisibilityChanged(boolean showing); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 3b9fcc78c932..24f02ac1a6cf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -54,6 +54,9 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.annotations.ExternalThread; +import com.android.wm.shell.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; import java.io.PrintWriter; @@ -61,7 +64,8 @@ import java.io.PrintWriter; * Manages and manipulates the one handed states, transitions, and gesture for phones. */ public class OneHandedController implements RemoteCallable<OneHandedController>, - DisplayChangeController.OnDisplayChangingListener { + DisplayChangeController.OnDisplayChangingListener, ConfigurationChangeListener, + KeyguardChangeListener { private static final String TAG = "OneHandedController"; private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE = @@ -81,6 +85,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, private Context mContext; + private final ShellController mShellController; private final AccessibilityManager mAccessibilityManager; private final DisplayController mDisplayController; private final OneHandedSettingsUtil mOneHandedSettingsUtil; @@ -188,8 +193,9 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, * Creates {@link OneHandedController}, returns {@code null} if the feature is not supported. */ public static OneHandedController create( - Context context, WindowManager windowManager, DisplayController displayController, - DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener, + Context context, ShellController shellController, WindowManager windowManager, + DisplayController displayController, DisplayLayout displayLayout, + TaskStackListenerImpl taskStackListener, InteractionJankMonitor jankMonitor, UiEventLogger uiEventLogger, ShellExecutor mainExecutor, Handler mainHandler) { OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil(); @@ -207,14 +213,15 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, context, displayLayout, settingsUtil, animationController, tutorialHandler, jankMonitor, mainExecutor); OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger); - return new OneHandedController(context, displayController, organizer, touchHandler, - tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState, - oneHandedUiEventsLogger, taskStackListener, + return new OneHandedController(context, shellController, displayController, organizer, + touchHandler, tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, + oneHandedState, oneHandedUiEventsLogger, taskStackListener, mainExecutor, mainHandler); } @VisibleForTesting OneHandedController(Context context, + ShellController shellController, DisplayController displayController, OneHandedDisplayAreaOrganizer displayAreaOrganizer, OneHandedTouchHandler touchHandler, @@ -228,6 +235,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, ShellExecutor mainExecutor, Handler mainHandler) { mContext = context; + mShellController = shellController; mOneHandedSettingsUtil = settingsUtil; mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil; mDisplayAreaOrganizer = displayAreaOrganizer; @@ -272,6 +280,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, mAccessibilityStateChangeListener); mState.addSListeners(mTutorialHandler); + mShellController.addConfigurationChangeListener(this); + mShellController.addKeyguardChangeListener(this); } public OneHanded asOneHanded() { @@ -587,7 +597,8 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, mLockedDisabled = locked && !enabled; } - private void onConfigChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { if (mTutorialHandler == null) { return; } @@ -597,8 +608,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, mTutorialHandler.onConfigurationChanged(); } - private void onKeyguardVisibilityChanged(boolean showing) { - mKeyguardShowing = showing; + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + mKeyguardShowing = visible; + stopOneHanded(); } private void onUserSwitch(int newUserId) { @@ -667,9 +681,12 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, return; } + if (mState.getState() == STATE_ACTIVE) { + mOneHandedUiEventLogger.writeEvent( + OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT); + } + mDisplayAreaOrganizer.onRotateDisplay(mContext, toRotation, wct); - mOneHandedUiEventLogger.writeEvent( - OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT); } /** @@ -743,25 +760,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, } @Override - public void onConfigChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - OneHandedController.this.onConfigChanged(newConfig); - }); - } - - @Override public void onUserSwitch(int userId) { mMainExecutor.execute(() -> { OneHandedController.this.onUserSwitch(userId); }); } - - @Override - public void onKeyguardVisibilityChanged(boolean showing) { - mMainExecutor.execute(() -> { - OneHandedController.this.onKeyguardVisibilityChanged(showing); - }); - } } /** 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 bbc47e47afc5..38631ce26cd1 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 @@ -16,7 +16,6 @@ package com.android.wm.shell.pip; -import android.content.res.Configuration; import android.graphics.Rect; import com.android.wm.shell.common.annotations.ExternalThread; @@ -44,24 +43,6 @@ public interface Pip { } /** - * Called when configuration is changed. - */ - default void onConfigurationChanged(Configuration newConfig) { - } - - /** - * Called when display size or font size of settings changed - */ - default void onDensityOrFontScaleChanged() { - } - - /** - * Called when overlay package change invoked. - */ - default void onOverlayChanged() { - } - - /** * Called when SysUI state changed. * * @param isSysUiStateValid Is SysUI state valid or not. @@ -120,23 +101,6 @@ public interface Pip { default void removePipExclusionBoundsChangeListener(Consumer<Rect> listener) { } /** - * Called when the visibility of keyguard is changed. - * @param showing {@code true} if keyguard is now showing, {@code false} otherwise. - * @param animating {@code true} if system is animating between keyguard and surface behind, - * this only makes sense when showing is {@code false}. - */ - default void onKeyguardVisibilityChanged(boolean showing, boolean animating) { } - - /** - * Called when the dismissing animation keyguard and surfaces behind is finished. - * See also {@link #onKeyguardVisibilityChanged(boolean, boolean)}. - * - * TODO(b/206741900) deprecate this path once we're able to animate the PiP window as part of - * keyguard dismiss animation. - */ - default void onKeyguardDismissAnimationFinished() { } - - /** * Dump the current state and information if need. * * @param pw The stream to dump information to. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index c0bc108baada..3ac08a66100a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java @@ -39,6 +39,10 @@ public class PipSurfaceTransactionHelper { private int mCornerRadius; private int mShadowRadius; + public PipSurfaceTransactionHelper(Context context) { + onDensityOrFontScaleChanged(context); + } + /** * Called when display size or font size of settings changed * diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index da88c2de6c01..1155ea174ed1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -62,6 +62,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteException; import android.os.SystemClock; +import android.util.Log; import android.view.Display; import android.view.Surface; import android.view.SurfaceControl; @@ -444,7 +445,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, // When exit to fullscreen with Shell transition enabled, we update the Task windowing // mode directly so that it can also trigger display rotation and visibility update in // the same transition if there will be any. - wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); + wct.setWindowingMode(mToken, getOutPipWindowingMode()); // We can inherit the parent bounds as it is going to be fullscreen. The // destinationBounds calculated above will be incorrect if this is with rotation. wct.setBounds(mToken, null); @@ -543,7 +544,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, if (Transitions.ENABLE_SHELL_TRANSITIONS) { final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setBounds(mToken, null); - wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); + wct.setWindowingMode(mToken, getOutPipWindowingMode()); wct.reorder(mToken, false); mPipTransitionController.startExitTransition(TRANSIT_REMOVE_PIP, wct, null /* destinationBounds */); @@ -930,6 +931,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, /** Called when exiting PIP transition is finished to do the state cleanup. */ void onExitPipFinished(TaskInfo info) { + if (mLeash == null) { + // TODO(239461594): Remove once the double call to onExitPipFinished() is fixed + Log.w(TAG, "Warning, onExitPipFinished() called multiple times in the same sessino"); + return; + } + clearWaitForFixedRotation(); if (mSwipePipToHomeOverlay != null) { removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */); 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 3000998f210d..420d6067f420 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 @@ -87,6 +87,9 @@ 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.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; @@ -100,7 +103,7 @@ import java.util.function.Consumer; * Manages the picture-in-picture (PIP) UI and states for Phones. */ public class PipController implements PipTransitionController.PipTransitionCallback, - RemoteCallable<PipController> { + RemoteCallable<PipController>, ConfigurationChangeListener, KeyguardChangeListener { private static final String TAG = "PipController"; private Context mContext; @@ -119,6 +122,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb private TaskStackListenerImpl mTaskStackListener; private PipParamsChangedForwarder mPipParamsChangedForwarder; private Optional<OneHandedController> mOneHandedController; + private final ShellController mShellController; protected final PipImpl mImpl; private final Rect mTmpInsetBounds = new Rect(); @@ -290,13 +294,20 @@ public class PipController implements PipTransitionController.PipTransitionCallb * Instantiates {@link PipController}, returns {@code null} if the feature not supported. */ @Nullable - public static Pip create(Context context, DisplayController displayController, - PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm, - PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState, - PipMotionHelper pipMotionHelper, PipMediaController pipMediaController, - PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer, + public static Pip create(Context context, + ShellController shellController, + DisplayController displayController, + PipAppOpsListener pipAppOpsListener, + PipBoundsAlgorithm pipBoundsAlgorithm, + PipKeepClearAlgorithm pipKeepClearAlgorithm, + PipBoundsState pipBoundsState, + PipMotionHelper pipMotionHelper, + PipMediaController pipMediaController, + PhonePipMenuController phonePipMenuController, + PipTaskOrganizer pipTaskOrganizer, PipTransitionState pipTransitionState, - PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController, + PipTouchHandler pipTouchHandler, + PipTransitionController pipTransitionController, WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, @@ -308,9 +319,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb return null; } - return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm, - pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController, - phonePipMenuController, pipTaskOrganizer, pipTransitionState, + return new PipController(context, shellController, displayController, pipAppOpsListener, + pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, + pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, oneHandedController, mainExecutor) @@ -318,6 +329,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb } protected PipController(Context context, + ShellController shellController, DisplayController displayController, PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm, @@ -343,6 +355,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb } mContext = context; + mShellController = shellController; mImpl = new PipImpl(); mWindowManagerShellWrapper = windowManagerShellWrapper; mDisplayController = displayController; @@ -513,6 +526,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb } }); }); + + mShellController.addConfigurationChangeListener(this); + mShellController.addKeyguardChangeListener(this); } @Override @@ -525,18 +541,21 @@ public class PipController implements PipTransitionController.PipTransitionCallb return mMainExecutor; } - private void onConfigurationChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { mPipBoundsAlgorithm.onConfigurationChanged(mContext); mTouchHandler.onConfigurationChanged(); mPipBoundsState.onConfigurationChanged(); } - private void onDensityOrFontScaleChanged() { + @Override + public void onDensityOrFontScaleChanged() { mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext); onPipResourceDimensionsChanged(); } - private void onOverlayChanged() { + @Override + public void onThemeChanged() { mTouchHandler.onOverlayChanged(); onDisplayChanged(new DisplayLayout(mContext, mContext.getDisplay()), false /* saveRestoreSnapFraction */); @@ -644,21 +663,24 @@ public class PipController implements PipTransitionController.PipTransitionCallb * finished first to reset the visibility of PiP window. * See also {@link #onKeyguardDismissAnimationFinished()} */ - private void onKeyguardVisibilityChanged(boolean keyguardShowing, boolean animating) { + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { if (!mPipTaskOrganizer.isInPip()) { return; } - if (keyguardShowing) { + if (visible) { mIsKeyguardShowingOrAnimating = true; hidePipMenu(null /* onStartCallback */, null /* onEndCallback */); mPipTaskOrganizer.setPipVisibility(false); - } else if (!animating) { + } else if (!animatingDismiss) { mIsKeyguardShowingOrAnimating = false; mPipTaskOrganizer.setPipVisibility(true); } } - private void onKeyguardDismissAnimationFinished() { + @Override + public void onKeyguardDismissAnimationFinished() { if (mPipTaskOrganizer.isInPip()) { mIsKeyguardShowingOrAnimating = false; mPipTaskOrganizer.setPipVisibility(true); @@ -923,27 +945,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb } @Override - public void onConfigurationChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - PipController.this.onConfigurationChanged(newConfig); - }); - } - - @Override - public void onDensityOrFontScaleChanged() { - mMainExecutor.execute(() -> { - PipController.this.onDensityOrFontScaleChanged(); - }); - } - - @Override - public void onOverlayChanged() { - mMainExecutor.execute(() -> { - PipController.this.onOverlayChanged(); - }); - } - - @Override public void onSystemUiStateChanged(boolean isSysUiStateValid, int flag) { mMainExecutor.execute(() -> { PipController.this.onSystemUiStateChanged(isSysUiStateValid, flag); @@ -1000,18 +1001,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb } @Override - public void onKeyguardVisibilityChanged(boolean showing, boolean animating) { - mMainExecutor.execute(() -> { - PipController.this.onKeyguardVisibilityChanged(showing, animating); - }); - } - - @Override - public void onKeyguardDismissAnimationFinished() { - mMainExecutor.execute(PipController.this::onKeyguardDismissAnimationFinished); - } - - @Override public void dump(PrintWriter pw) { try { mMainExecutor.executeBlocking(() -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index fa48def9c7d7..a24d9618032d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -49,6 +49,8 @@ import com.android.wm.shell.pip.PipParamsChangedForwarder; import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.sysui.ConfigurationChangeListener; +import com.android.wm.shell.sysui.ShellController; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -61,7 +63,8 @@ import java.util.Set; */ public class TvPipController implements PipTransitionController.PipTransitionCallback, TvPipBoundsController.PipBoundsListener, TvPipMenuController.Delegate, - TvPipNotificationController.Delegate, DisplayController.OnDisplaysChangedListener { + TvPipNotificationController.Delegate, DisplayController.OnDisplaysChangedListener, + ConfigurationChangeListener { private static final String TAG = "TvPipController"; static final boolean DEBUG = false; @@ -93,6 +96,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private final Context mContext; + private final ShellController mShellController; private final TvPipBoundsState mTvPipBoundsState; private final TvPipBoundsAlgorithm mTvPipBoundsAlgorithm; private final TvPipBoundsController mTvPipBoundsController; @@ -117,6 +121,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal public static Pip create( Context context, + ShellController shellController, TvPipBoundsState tvPipBoundsState, TvPipBoundsAlgorithm tvPipBoundsAlgorithm, TvPipBoundsController tvPipBoundsController, @@ -133,6 +138,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal ShellExecutor mainExecutor) { return new TvPipController( context, + shellController, tvPipBoundsState, tvPipBoundsAlgorithm, tvPipBoundsController, @@ -151,6 +157,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private TvPipController( Context context, + ShellController shellController, TvPipBoundsState tvPipBoundsState, TvPipBoundsAlgorithm tvPipBoundsAlgorithm, TvPipBoundsController tvPipBoundsController, @@ -167,6 +174,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal ShellExecutor mainExecutor) { mContext = context; mMainExecutor = mainExecutor; + mShellController = shellController; mTvPipBoundsState = tvPipBoundsState; mTvPipBoundsState.setDisplayId(context.getDisplayId()); @@ -193,9 +201,12 @@ public class TvPipController implements PipTransitionController.PipTransitionCal registerTaskStackListenerCallback(taskStackListener); registerWmShellPinnedStackListener(wmShell); displayController.addDisplayWindowListener(this); + + mShellController.addConfigurationChangeListener(this); } - private void onConfigurationChanged(Configuration newConfig) { + @Override + public void onConfigurationChanged(Configuration newConfig) { if (DEBUG) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState)); @@ -669,13 +680,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal private class TvPipImpl implements Pip { @Override - public void onConfigurationChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - TvPipController.this.onConfigurationChanged(newConfig); - }); - } - - @Override public void registerSessionListenerForCurrentUser() { mMainExecutor.execute(() -> { TvPipController.this.registerSessionListenerForCurrentUser(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java index e31e0d674bec..b2961518b66a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java @@ -44,6 +44,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM_SHELL), WM_SHELL_SPLIT_SCREEN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_SHELL), + WM_SHELL_SYSUI_EVENTS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, + Consts.TAG_WM_SHELL), TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest"); private final boolean mEnabled; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java index 29b6311e5041..e73b799b7a3d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java @@ -77,12 +77,6 @@ public interface SplitScreen { return null; } - /** - * Called when the visibility of the keyguard changes. - * @param showing Indicates if the keyguard is now visible. - */ - void onKeyguardVisibilityChanged(boolean showing); - /** Called when device waking up finished. */ void onFinishedWakingUp(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 21bea4674805..7fb961fc0761 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -80,6 +80,8 @@ import com.android.wm.shell.draganddrop.DragAndDropPolicy; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreen.StageType; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.LegacyTransitions; import com.android.wm.shell.transition.Transitions; @@ -99,7 +101,7 @@ import java.util.concurrent.Executor; */ // TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen. public class SplitScreenController implements DragAndDropPolicy.Starter, - RemoteCallable<SplitScreenController> { + RemoteCallable<SplitScreenController>, KeyguardChangeListener { private static final String TAG = SplitScreenController.class.getSimpleName(); public static final int EXIT_REASON_UNKNOWN = 0; @@ -127,6 +129,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Retention(RetentionPolicy.SOURCE) @interface ExitReason{} + private final ShellController mShellController; private final ShellTaskOrganizer mTaskOrganizer; private final SyncTransactionQueue mSyncQueue; private final Context mContext; @@ -147,7 +150,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, // outside the bounds of the roots by being reparented into a higher level fullscreen container private SurfaceControl mSplitTasksContainerLayer; - public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer, + public SplitScreenController(ShellController shellController, + ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, Context context, RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellExecutor mainExecutor, DisplayController displayController, @@ -155,6 +159,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, DisplayInsetsController displayInsetsController, Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider, Optional<RecentTasksController> recentTasks) { + mShellController = shellController; mTaskOrganizer = shellTaskOrganizer; mSyncQueue = syncQueue; mContext = context; @@ -185,6 +190,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void onOrganizerRegistered() { + mShellController.addKeyguardChangeListener(this); if (mStageCoordinator == null) { // TODO: Multi-display mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, @@ -283,8 +289,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason); } - public void onKeyguardVisibilityChanged(boolean showing) { - mStageCoordinator.onKeyguardVisibilityChanged(showing); + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + mStageCoordinator.onKeyguardVisibilityChanged(visible); } public void onFinishedWakingUp() { @@ -344,41 +352,31 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { + if (fillInIntent == null) { + fillInIntent = new Intent(); + } + // Flag this as a no-user-action launch to prevent sending user leaving event to the + // current top activity since it's going to be put into another side of the split. This + // prevents the current top activity from going into pip mode due to user leaving event. + fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION); + + // Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the + // split. + if (isLaunchingAdjacently(intent.getIntent(), position)) { + fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK"); + } + if (!ENABLE_SHELL_TRANSITIONS) { startIntentLegacy(intent, fillInIntent, position, options); return; } - try { - options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, - null /* wct */); - - if (fillInIntent == null) { - fillInIntent = new Intent(); - } - // Flag this as a no-user-action launch to prevent sending user leaving event to the - // current top activity since it's going to be put into another side of the split. This - // prevents the current top activity from going into pip mode due to user leaving event. - fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION); - - // Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the - // split. - if (isLaunchingAdjacently(intent.getIntent(), position)) { - fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK"); - } - - intent.send(mContext, 0, fillInIntent, null /* onFinished */, null /* handler */, - null /* requiredPermission */, options); - } catch (PendingIntent.CanceledException e) { - Slog.e(TAG, "Failed to launch task", e); - } + mStageCoordinator.startIntent(intent, fillInIntent, position, options); } - private void startIntentLegacy(PendingIntent intent, @Nullable Intent fillInIntent, + private void startIntentLegacy(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { - boolean startSameActivityAdjacently = isLaunchingAdjacently(intent.getIntent(), position); - final WindowContainerTransaction evictWct = new WindowContainerTransaction(); mStageCoordinator.prepareEvictChildTasks(position, evictWct); @@ -389,8 +387,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, IRemoteAnimationFinishedCallback finishedCallback, SurfaceControl.Transaction t) { if (apps == null || apps.length == 0) { - if (startSameActivityAdjacently) { - // Switch split position if dragging the same activity to another side. + // Switch the split position if launching as MULTIPLE_TASK failed. + if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) { setSideStagePosition(SplitLayout.reversePosition( mStageCoordinator.getSideStagePosition())); } @@ -400,8 +398,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return; } - mStageCoordinator.updateSurfaceBounds(null /* layout */, t, - false /* applyResizingOffset */); for (int i = 0; i < apps.length; ++i) { if (apps[i].mode == MODE_OPENING) { t.show(apps[i].leash); @@ -424,18 +420,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, final WindowContainerTransaction wct = new WindowContainerTransaction(); options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct); - // Flag this as a no-user-action launch to prevent sending user leaving event to the current - // top activity since it's going to be put into another side of the split. This prevents the - // current top activity from going into pip mode due to user leaving event. - if (fillInIntent == null) { - fillInIntent = new Intent(); - } - fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION); - if (startSameActivityAdjacently) { - fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK"); - } - wct.sendPendingIntent(intent, fillInIntent, options); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); } @@ -658,13 +642,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } @Override - public void onKeyguardVisibilityChanged(boolean showing) { - mMainExecutor.execute(() -> { - SplitScreenController.this.onKeyguardVisibilityChanged(showing); - }); - } - - @Override public void onFinishedWakingUp() { mMainExecutor.execute(() -> { SplitScreenController.this.onFinishedWakingUp(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java index 056cd5813861..83bdf8bfb727 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java @@ -62,13 +62,12 @@ class SplitScreenTransitions { private final Runnable mOnFinish; DismissTransition mPendingDismiss = null; - IBinder mPendingEnter = null; - IBinder mPendingRecent = null; + TransitSession mPendingEnter = null; + TransitSession mPendingRecent = null; private IBinder mAnimatingTransition = null; OneShotRemoteHandler mPendingRemoteHandler = null; private OneShotRemoteHandler mActiveRemoteHandler = null; - private boolean mEnterTransitionMerged; private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish; @@ -145,7 +144,7 @@ class SplitScreenTransitions { continue; } - if (transition == mPendingEnter && (mainRoot.equals(change.getContainer()) + if (isPendingEnter(transition) && (mainRoot.equals(change.getContainer()) || sideRoot.equals(change.getContainer()))) { t.setPosition(leash, change.getEndAbsBounds().left, change.getEndAbsBounds().top); t.setWindowCrop(leash, change.getEndAbsBounds().width(), @@ -171,12 +170,40 @@ class SplitScreenTransitions { onFinish(null /* wct */, null /* wctCB */); } + boolean isPendingTransition(IBinder transition) { + return isPendingEnter(transition) + || isPendingDismiss(transition) + || isPendingRecent(transition); + } + + boolean isPendingEnter(IBinder transition) { + return mPendingEnter != null && mPendingEnter.mTransition == transition; + } + + boolean isPendingRecent(IBinder transition) { + return mPendingRecent != null && mPendingRecent.mTransition == transition; + } + + boolean isPendingDismiss(IBinder transition) { + return mPendingDismiss != null && mPendingDismiss.mTransition == transition; + } + /** Starts a transition to enter split with a remote transition animator. */ - IBinder startEnterTransition(@WindowManager.TransitionType int transitType, - @NonNull WindowContainerTransaction wct, @Nullable RemoteTransition remoteTransition, - @NonNull Transitions.TransitionHandler handler) { + IBinder startEnterTransition( + @WindowManager.TransitionType int transitType, + WindowContainerTransaction wct, + @Nullable RemoteTransition remoteTransition, + Transitions.TransitionHandler handler, + @Nullable TransitionCallback callback) { final IBinder transition = mTransitions.startTransition(transitType, wct, handler); - mPendingEnter = transition; + setEnterTransition(transition, remoteTransition, callback); + return transition; + } + + /** Sets a transition to enter split. */ + void setEnterTransition(@NonNull IBinder transition, + @Nullable RemoteTransition remoteTransition, @Nullable TransitionCallback callback) { + mPendingEnter = new TransitSession(transition, callback); if (remoteTransition != null) { // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff) @@ -184,7 +211,9 @@ class SplitScreenTransitions { mTransitions.getMainExecutor(), remoteTransition); mPendingRemoteHandler.setTransition(transition); } - return transition; + + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition " + + " deduced Enter split screen"); } /** Starts a transition to dismiss split. */ @@ -209,8 +238,8 @@ class SplitScreenTransitions { } void setRecentTransition(@NonNull IBinder transition, - @Nullable RemoteTransition remoteTransition) { - mPendingRecent = transition; + @Nullable RemoteTransition remoteTransition, @Nullable TransitionCallback callback) { + mPendingRecent = new TransitSession(transition, callback); if (remoteTransition != null) { // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff) @@ -226,6 +255,18 @@ class SplitScreenTransitions { void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) { if (mergeTarget != mAnimatingTransition) return; + + if (isPendingEnter(transition) && isPendingRecent(mergeTarget)) { + mPendingRecent.mCallback = new TransitionCallback() { + @Override + public void onTransitionFinished(WindowContainerTransaction finishWct, + SurfaceControl.Transaction finishT) { + // Since there's an entering transition merged, recent transition no longer + // need to handle entering split screen after the transition finished. + } + }; + } + if (mActiveRemoteHandler != null) { mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback); } else { @@ -247,38 +288,55 @@ class SplitScreenTransitions { } void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) { - if (aborted) return; + if (isPendingEnter(transition)) { + if (!aborted) { + // An enter transition got merged, appends the rest operations to finish entering + // split screen. + // TODO (b/238856352): Passed-in the proper finish transition to merge instead. + if (mFinishTransaction == null) { + mFinishTransaction = mTransactionPool.acquire(); + } + mStageCoordinator.finishEnterSplitScreen(mFinishTransaction); + } - // Once a pending enter transition got merged, make sure to append the reset of finishing - // operations to the finish transition. - if (transition == mPendingEnter) { - mFinishTransaction = mTransactionPool.acquire(); - mStageCoordinator.finishEnterSplitScreen(mFinishTransaction); + mPendingEnter.mCallback.onTransitionConsumed(aborted); mPendingEnter = null; mPendingRemoteHandler = null; - mEnterTransitionMerged = true; + } else if (isPendingDismiss(transition)) { + mPendingDismiss.mCallback.onTransitionConsumed(aborted); + mPendingDismiss = null; + } else if (isPendingRecent(transition)) { + mPendingRecent.mCallback.onTransitionConsumed(aborted); + mPendingRecent = null; + mPendingRemoteHandler = null; } } void onFinish(WindowContainerTransaction wct, WindowContainerTransactionCallback wctCB) { if (!mAnimations.isEmpty()) return; - if (mAnimatingTransition == mPendingEnter) { + + TransitionCallback callback = null; + if (isPendingEnter(mAnimatingTransition)) { + callback = mPendingEnter.mCallback; mPendingEnter = null; } - if (mPendingDismiss != null && mPendingDismiss.mTransition == mAnimatingTransition) { + if (isPendingDismiss(mAnimatingTransition)) { + callback = mPendingDismiss.mCallback; mPendingDismiss = null; } - if (mAnimatingTransition == mPendingRecent) { - if (!mEnterTransitionMerged) { - if (wct == null) wct = new WindowContainerTransaction(); - mStageCoordinator.onRecentTransitionFinished(wct, mFinishTransaction); - } + if (isPendingRecent(mAnimatingTransition)) { + callback = mPendingRecent.mCallback; mPendingRecent = null; } + + if (callback != null) { + if (wct == null) wct = new WindowContainerTransaction(); + callback.onTransitionFinished(wct, mFinishTransaction); + } + mPendingRemoteHandler = null; mActiveRemoteHandler = null; mAnimatingTransition = null; - mEnterTransitionMerged = false; mOnFinish.run(); if (mFinishTransaction != null) { @@ -382,17 +440,34 @@ class SplitScreenTransitions { || info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN; } - /** Bundled information of dismiss transition. */ - static class DismissTransition { - IBinder mTransition; + /** Clean-up callbacks for transition. */ + interface TransitionCallback { + /** Calls when the transition got consumed. */ + default void onTransitionConsumed(boolean aborted) {} + + /** Calls when the transition finished. */ + default void onTransitionFinished(WindowContainerTransaction finishWct, + SurfaceControl.Transaction finishT) {} + } - int mReason; + /** Session for a transition and its clean-up callback. */ + static class TransitSession { + final IBinder mTransition; + TransitionCallback mCallback; - @SplitScreen.StageType - int mDismissTop; + TransitSession(IBinder transition, @Nullable TransitionCallback callback) { + mTransition = transition; + mCallback = callback != null ? callback : new TransitionCallback() {}; + } + } + + /** Bundled information of dismiss transition. */ + static class DismissTransition extends TransitSession { + final int mReason; + final @SplitScreen.StageType int mDismissTop; DismissTransition(IBinder transition, int reason, int dismissTop) { - this.mTransition = transition; + super(transition, null /* callback */); this.mReason = reason; this.mDismissTop = dismissTop; } 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 2229e26b9343..3c7db33bccf2 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 @@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.TRANSIT_CHANGE; @@ -214,6 +215,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } }; + private final SplitScreenTransitions.TransitionCallback mRecentTransitionCallback = + new SplitScreenTransitions.TransitionCallback() { + @Override + public void onTransitionFinished(WindowContainerTransaction finishWct, + SurfaceControl.Transaction finishT) { + // Check if the recent transition is finished by returning to the current split, so we + // can restore the divider bar. + for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) { + final WindowContainerTransaction.HierarchyOp op = + finishWct.getHierarchyOps().get(i); + final IBinder container = op.getContainer(); + if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop() + && (mMainStage.containsContainer(container) + || mSideStage.containsContainer(container))) { + setDividerVisibility(true, finishT); + return; + } + } + + // Dismiss the split screen if it's not returning to split. + prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct); + setSplitsVisible(false); + setDividerVisibility(false, finishT); + logExit(EXIT_REASON_UNKNOWN); + } + }; + StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, ShellTaskOrganizer taskOrganizer, DisplayController displayController, DisplayImeController displayImeController, @@ -337,15 +365,23 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final WindowContainerTransaction evictWct = new WindowContainerTransaction(); targetStage.evictAllChildren(evictWct); targetStage.addTask(task, wct); - if (!evictWct.isEmpty()) { - wct.merge(evictWct, true /* transfer */); - } if (ENABLE_SHELL_TRANSITIONS) { prepareEnterSplitScreen(wct); - mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, - wct, null, this); + mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, + null, this, new SplitScreenTransitions.TransitionCallback() { + @Override + public void onTransitionFinished(WindowContainerTransaction finishWct, + SurfaceControl.Transaction finishT) { + if (!evictWct.isEmpty()) { + finishWct.merge(evictWct, true); + } + } + }); } else { + if (!evictWct.isEmpty()) { + wct.merge(evictWct, true /* transfer */); + } mTaskOrganizer.applyTransaction(wct); } return true; @@ -365,6 +401,39 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return result; } + /** Launches an activity into split. */ + void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, + @Nullable Bundle options) { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + prepareEvictChildTasks(position, evictWct); + + options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */); + wct.sendPendingIntent(intent, fillInIntent, options); + prepareEnterSplitScreen(wct, null /* taskInfo */, position); + + mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, null, this, + new SplitScreenTransitions.TransitionCallback() { + @Override + public void onTransitionConsumed(boolean aborted) { + // Switch the split position if launching as MULTIPLE_TASK failed. + if (aborted + && (fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) { + setSideStagePositionAnimated( + SplitLayout.reversePosition(mSideStagePosition)); + } + } + + @Override + public void onTransitionFinished(WindowContainerTransaction finishWct, + SurfaceControl.Transaction finishT) { + if (!evictWct.isEmpty()) { + finishWct.merge(evictWct, true); + } + } + }); + } + /** Starts 2 tasks in one transition. */ void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, @@ -395,7 +464,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, wct.startTask(sideTaskId, sideOptions); mSplitTransitions.startEnterTransition( - TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this); + TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this, null); } /** Starts 2 tasks in one legacy transition. */ @@ -617,11 +686,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } int getTaskId(@SplitPosition int splitPosition) { - if (mSideStagePosition == splitPosition) { - return mSideStage.getTopVisibleChildTaskId(); - } else { - return mMainStage.getTopVisibleChildTaskId(); + if (splitPosition == SPLIT_POSITION_UNDEFINED) { + return INVALID_TASK_ID; } + + return mSideStagePosition == splitPosition + ? mSideStage.getTopVisibleChildTaskId() + : mMainStage.getTopVisibleChildTaskId(); } void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) { @@ -861,6 +932,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.init(); setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + t.show(mRootTaskLeash); setSplitsVisible(true); mShouldUpdateRecents = true; updateRecentTasksSplitPair(); @@ -1211,7 +1283,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void onStageHasChildrenChanged(StageListenerImpl stageListener) { final boolean hasChildren = stageListener.mHasChildren; final boolean isSideStage = stageListener == mSideStageListener; - if (!hasChildren && !mIsExiting) { + if (!hasChildren && !mIsExiting && mMainStage.isActive()) { if (isSideStage && mMainStageListener.mVisible) { // Exit to main stage if side stage no longer has children. if (ENABLE_SHELL_TRANSITIONS) { @@ -1231,7 +1303,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, EXIT_REASON_APP_FINISHED); } } - } else if (isSideStage && !mMainStage.isActive()) { + } else if (isSideStage && hasChildren && !mMainStage.isActive()) { if (mFocusingTaskInfo != null && !isValidToEnterSplitScreen(mFocusingTaskInfo)) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mSideStage.removeAllTasks(wct, true); @@ -1543,14 +1615,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) { // Enter overview panel, so start recent transition. - mSplitTransitions.setRecentTransition(transition, - request.getRemoteTransition()); + mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(), + mRecentTransitionCallback); } else if (mSplitTransitions.mPendingRecent == null) { // If split-task is not controlled by recents animation // and occluded by the other fullscreen task, dismiss both. prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out); - mSplitTransitions.setDismissTransition(transition, - STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN); + mSplitTransitions.setDismissTransition( + transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN); } } } else { @@ -1558,7 +1630,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // One task is appearing into split, prepare to enter split screen. out = new WindowContainerTransaction(); prepareEnterSplitScreen(out); - mSplitTransitions.mPendingEnter = transition; + mSplitTransitions.setEnterTransition( + transition, request.getRemoteTransition(), null /* callback */); } } return out; @@ -1614,10 +1687,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - if (transition != mSplitTransitions.mPendingEnter - && transition != mSplitTransitions.mPendingRecent - && (mSplitTransitions.mPendingDismiss == null - || mSplitTransitions.mPendingDismiss.mTransition != transition)) { + if (!mSplitTransitions.isPendingTransition(transition)) { // Not entering or exiting, so just do some house-keeping and validation. // If we're not in split-mode, just abort so something else can handle it. @@ -1664,12 +1734,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } boolean shouldAnimate = true; - if (mSplitTransitions.mPendingEnter == transition) { + if (mSplitTransitions.isPendingEnter(transition)) { shouldAnimate = startPendingEnterAnimation(transition, info, startTransaction); - } else if (mSplitTransitions.mPendingRecent == transition) { + } else if (mSplitTransitions.isPendingRecent(transition)) { shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction); - } else if (mSplitTransitions.mPendingDismiss != null - && mSplitTransitions.mPendingDismiss.mTransition == transition) { + } else if (mSplitTransitions.isPendingDismiss(transition)) { shouldAnimate = startPendingDismissAnimation( mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction); } @@ -1837,28 +1906,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return true; } - void onRecentTransitionFinished(WindowContainerTransaction wct, - SurfaceControl.Transaction finishT) { - // Check if the recent transition is finished by returning to the current split so we can - // restore the divider bar. - for (int i = 0; i < wct.getHierarchyOps().size(); ++i) { - final WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i); - final IBinder container = op.getContainer(); - if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop() - && (mMainStage.containsContainer(container) - || mSideStage.containsContainer(container))) { - setDividerVisibility(true, finishT); - return; - } - } - - // Dismiss the split screen is it's not returning to split. - prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct); - setSplitsVisible(false); - setDividerVisibility(false, finishT); - logExit(EXIT_REASON_UNKNOWN); - } - private void addDividerBarToTransition(@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, boolean show) { final SurfaceControl leash = mSplitLayout.getDividerLeash(); 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 19d3acbf28d4..b70bde3a64ee 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 @@ -228,12 +228,13 @@ public class TaskSnapshotWindow { final InsetsState tmpInsetsState = new InsetsState(); final InputChannel tmpInputChannel = new InputChannel(); + final float[] sizeCompatScale = { 1f }; try { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#addToDisplay"); final int res = session.addToDisplay(window, layoutParams, View.GONE, displayId, info.requestedVisibilities, tmpInputChannel, tmpInsetsState, tmpControls, - new Rect()); + new Rect(), sizeCompatScale); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (res < 0) { Slog.w(TAG, "Failed to add snapshot starting window res=" + res); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ConfigurationChangeListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ConfigurationChangeListener.java new file mode 100644 index 000000000000..2fca8f0ecc76 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ConfigurationChangeListener.java @@ -0,0 +1,51 @@ +/* + * 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.wm.shell.sysui; + +import android.content.res.Configuration; + +/** + * Callbacks for when the configuration changes. + */ +public interface ConfigurationChangeListener { + + /** + * Called when a configuration changes. This precedes all the following callbacks. + */ + default void onConfigurationChanged(Configuration newConfiguration) {} + + /** + * Convenience method to the above, called when the density or font scale changes. + */ + default void onDensityOrFontScaleChanged() {} + + /** + * Convenience method to the above, called when the smallest screen width changes. + */ + default void onSmallestScreenWidthChanged() {} + + /** + * Convenience method to the above, called when the system theme changes, including dark/light + * UI_MODE changes. + */ + default void onThemeChanged() {} + + /** + * Convenience method to the above, called when the local list or layout direction changes. + */ + default void onLocaleOrLayoutDirectionChanged() {} +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/KeyguardChangeListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/KeyguardChangeListener.java new file mode 100644 index 000000000000..1c0b35894acd --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/KeyguardChangeListener.java @@ -0,0 +1,36 @@ +/* + * 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.wm.shell.sysui; + +/** + * Callbacks for when the keyguard changes. + */ +public interface KeyguardChangeListener { + /** + * Notifies the Shell that the keyguard is showing (and if so, whether it is occluded). + */ + default void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) {} + + /** + * Notifies the Shell when the keyguard dismiss animation has finished. + * + * TODO(b/206741900) deprecate this path once we're able to animate the PiP window as part of + * keyguard dismiss animation. + */ + default void onKeyguardDismissAnimationFinished() {} +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellCommandHandler.java index c5f7c19518a7..0427efb30b9f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellCommandHandler.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.wm.shell; +package com.android.wm.shell.sysui; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController; import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer; @@ -34,8 +35,8 @@ import java.util.Optional; * * Use with {@code adb shell dumpsys activity service SystemUIService WMShell ...}. */ -public final class ShellCommandHandlerImpl { - private static final String TAG = ShellCommandHandlerImpl.class.getSimpleName(); +public final class ShellCommandHandler { + private static final String TAG = ShellCommandHandler.class.getSimpleName(); private final Optional<SplitScreenController> mSplitScreenOptional; private final Optional<Pip> mPipOptional; @@ -45,9 +46,9 @@ public final class ShellCommandHandlerImpl { private final ShellTaskOrganizer mShellTaskOrganizer; private final KidsModeTaskOrganizer mKidsModeTaskOrganizer; private final ShellExecutor mMainExecutor; - private final HandlerImpl mImpl = new HandlerImpl(); - public ShellCommandHandlerImpl( + public ShellCommandHandler( + ShellController shellController, ShellTaskOrganizer shellTaskOrganizer, KidsModeTaskOrganizer kidsModeTaskOrganizer, Optional<SplitScreenController> splitScreenOptional, @@ -64,14 +65,12 @@ public final class ShellCommandHandlerImpl { mOneHandedOptional = oneHandedOptional; mHideDisplayCutout = hideDisplayCutout; mMainExecutor = mainExecutor; - } - - public ShellCommandHandler asShellCommandHandler() { - return mImpl; + // TODO(238217847): To be removed once the command handler dependencies are inverted + shellController.setShellCommandHandler(this); } /** Dumps WM Shell internal state. */ - private void dump(PrintWriter pw) { + public void dump(PrintWriter pw) { mShellTaskOrganizer.dump(pw, ""); pw.println(); pw.println(); @@ -91,7 +90,7 @@ public final class ShellCommandHandlerImpl { /** Returns {@code true} if command was found and executed. */ - private boolean handleCommand(final String[] args, PrintWriter pw) { + public boolean handleCommand(final String[] args, PrintWriter pw) { if (args.length < 2) { // Argument at position 0 is "WMShell". return false; @@ -164,28 +163,4 @@ public final class ShellCommandHandlerImpl { pw.println(" Sets the position of the side-stage."); return true; } - - private class HandlerImpl implements ShellCommandHandler { - @Override - public void dump(PrintWriter pw) { - try { - mMainExecutor.executeBlocking(() -> ShellCommandHandlerImpl.this.dump(pw)); - } catch (InterruptedException e) { - throw new RuntimeException("Failed to dump the Shell in 2s", e); - } - } - - @Override - public boolean handleCommand(String[] args, PrintWriter pw) { - try { - boolean[] result = new boolean[1]; - mMainExecutor.executeBlocking(() -> { - result[0] = ShellCommandHandlerImpl.this.handleCommand(args, pw); - }); - return result[0]; - } catch (InterruptedException e) { - throw new RuntimeException("Failed to handle Shell command in 2s", e); - } - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java new file mode 100644 index 000000000000..618028c1544f --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java @@ -0,0 +1,240 @@ +/* + * 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.wm.shell.sysui; + +import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS; +import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE; +import static android.content.pm.ActivityInfo.CONFIG_LAYOUT_DIRECTION; +import static android.content.pm.ActivityInfo.CONFIG_LOCALE; +import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; +import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; + +import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SYSUI_EVENTS; + +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.common.annotations.ExternalThread; + +import java.io.PrintWriter; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Handles event callbacks from SysUI that can be used within the Shell. + */ +public class ShellController { + private static final String TAG = ShellController.class.getSimpleName(); + + private final ShellExecutor mMainExecutor; + private final ShellInterfaceImpl mImpl = new ShellInterfaceImpl(); + + private ShellInit mShellInit; + private ShellCommandHandler mShellCommandHandler; + + private final CopyOnWriteArrayList<ConfigurationChangeListener> mConfigChangeListeners = + new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList<KeyguardChangeListener> mKeyguardChangeListeners = + new CopyOnWriteArrayList<>(); + private Configuration mLastConfiguration; + + + public ShellController(ShellExecutor mainExecutor) { + mMainExecutor = mainExecutor; + } + + /** + * Returns the external interface to this controller. + */ + public ShellInterface asShell() { + return mImpl; + } + + /** + * Sets the init handler to call back to. + * TODO(238217847): This is only exposed this way until we can remove the dependencies from the + * init handler to other classes. + */ + public void setShellInit(ShellInit shellInit) { + mShellInit = shellInit; + } + + /** + * Sets the command handler to call back to. + * TODO(238217847): This is only exposed this way until we can remove the dependencies from the + * command handler to other classes. + */ + public void setShellCommandHandler(ShellCommandHandler shellCommandHandler) { + mShellCommandHandler = shellCommandHandler; + } + + /** + * Adds a new configuration listener. The configuration change callbacks are not made in any + * particular order. + */ + public void addConfigurationChangeListener(ConfigurationChangeListener listener) { + mConfigChangeListeners.remove(listener); + mConfigChangeListeners.add(listener); + } + + /** + * Removes an existing configuration listener. + */ + public void removeConfigurationChangeListener(ConfigurationChangeListener listener) { + mConfigChangeListeners.remove(listener); + } + + /** + * Adds a new Keyguard listener. The Keyguard change callbacks are not made in any + * particular order. + */ + public void addKeyguardChangeListener(KeyguardChangeListener listener) { + mKeyguardChangeListeners.remove(listener); + mKeyguardChangeListeners.add(listener); + } + + /** + * Removes an existing Keyguard listener. + */ + public void removeKeyguardChangeListener(KeyguardChangeListener listener) { + mKeyguardChangeListeners.remove(listener); + } + + @VisibleForTesting + void onConfigurationChanged(Configuration newConfig) { + // The initial config is send on startup and doesn't trigger listener callbacks + if (mLastConfiguration == null) { + mLastConfiguration = new Configuration(newConfig); + ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "Initial Configuration: %s", newConfig); + return; + } + + final int diff = newConfig.diff(mLastConfiguration); + ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "New configuration change: %s", newConfig); + ProtoLog.v(WM_SHELL_SYSUI_EVENTS, "\tchanges=%s", + Configuration.configurationDiffToString(diff)); + final boolean densityFontScaleChanged = (diff & CONFIG_FONT_SCALE) != 0 + || (diff & ActivityInfo.CONFIG_DENSITY) != 0; + final boolean smallestScreenWidthChanged = (diff & CONFIG_SMALLEST_SCREEN_SIZE) != 0; + final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0 + || (diff & CONFIG_UI_MODE) != 0; + final boolean localOrLayoutDirectionChanged = (diff & CONFIG_LOCALE) != 0 + || (diff & CONFIG_LAYOUT_DIRECTION) != 0; + + // Update the last configuration and call listeners + mLastConfiguration.updateFrom(newConfig); + for (ConfigurationChangeListener listener : mConfigChangeListeners) { + listener.onConfigurationChanged(newConfig); + if (densityFontScaleChanged) { + listener.onDensityOrFontScaleChanged(); + } + if (smallestScreenWidthChanged) { + listener.onSmallestScreenWidthChanged(); + } + if (themeChanged) { + listener.onThemeChanged(); + } + if (localOrLayoutDirectionChanged) { + listener.onLocaleOrLayoutDirectionChanged(); + } + } + } + + @VisibleForTesting + void onKeyguardVisibilityChanged(boolean visible, boolean occluded, boolean animatingDismiss) { + for (KeyguardChangeListener listener : mKeyguardChangeListeners) { + listener.onKeyguardVisibilityChanged(visible, occluded, animatingDismiss); + } + } + + @VisibleForTesting + void onKeyguardDismissAnimationFinished() { + for (KeyguardChangeListener listener : mKeyguardChangeListeners) { + listener.onKeyguardDismissAnimationFinished(); + } + } + + public void dump(@NonNull PrintWriter pw, String prefix) { + final String innerPrefix = prefix + " "; + pw.println(prefix + TAG); + pw.println(innerPrefix + "mConfigChangeListeners=" + mConfigChangeListeners.size()); + pw.println(innerPrefix + "mLastConfiguration=" + mLastConfiguration); + pw.println(innerPrefix + "mKeyguardChangeListeners=" + mKeyguardChangeListeners.size()); + } + + /** + * The interface for calls from outside the Shell, within the host process. + */ + @ExternalThread + private class ShellInterfaceImpl implements ShellInterface { + + @Override + public void onInit() { + try { + mMainExecutor.executeBlocking(() -> mShellInit.init()); + } catch (InterruptedException e) { + throw new RuntimeException("Failed to initialize the Shell in 2s", e); + } + } + + @Override + public void dump(PrintWriter pw) { + try { + mMainExecutor.executeBlocking(() -> mShellCommandHandler.dump(pw)); + } catch (InterruptedException e) { + throw new RuntimeException("Failed to dump the Shell in 2s", e); + } + } + + @Override + public boolean handleCommand(String[] args, PrintWriter pw) { + try { + boolean[] result = new boolean[1]; + mMainExecutor.executeBlocking(() -> { + result[0] = mShellCommandHandler.handleCommand(args, pw); + }); + return result[0]; + } catch (InterruptedException e) { + throw new RuntimeException("Failed to handle Shell command in 2s", e); + } + } + + @Override + public void onConfigurationChanged(Configuration newConfiguration) { + mMainExecutor.execute(() -> + ShellController.this.onConfigurationChanged(newConfiguration)); + } + + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + mMainExecutor.execute(() -> + ShellController.this.onKeyguardVisibilityChanged(visible, occluded, + animatingDismiss)); + } + + @Override + public void onKeyguardDismissAnimationFinished() { + mMainExecutor.execute(() -> + ShellController.this.onKeyguardDismissAnimationFinished()); + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java index 5a94a0d6f6a5..dd7fab7c5f46 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell; +package com.android.wm.shell.sysui; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT; @@ -26,14 +26,15 @@ import android.util.Pair; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.activityembedding.ActivityEmbeddingController; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropController; -import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.fullscreen.FullscreenTaskListener; import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer; import com.android.wm.shell.pip.phone.PipTouchHandler; @@ -52,8 +53,8 @@ import java.util.Optional; * The entry point implementation into the shell for initializing shell internal state. Classes * which need to setup on start should inject an instance of this class and add an init callback. */ -public class ShellInitImpl { - private static final String TAG = ShellInitImpl.class.getSimpleName(); +public class ShellInit { + private static final String TAG = ShellInit.class.getSimpleName(); private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; @@ -67,18 +68,19 @@ public class ShellInitImpl { private final FullscreenTaskListener mFullscreenTaskListener; private final Optional<UnfoldAnimationController> mUnfoldController; private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler; - private final Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional; + private final Optional<FreeformComponents> mFreeformComponentsOptional; private final ShellExecutor mMainExecutor; private final Transitions mTransitions; private final StartingWindowController mStartingWindow; private final Optional<RecentTasksController> mRecentTasks; + private final Optional<ActivityEmbeddingController> mActivityEmbeddingOptional; - private final InitImpl mImpl = new InitImpl(); // An ordered list of init callbacks to be made once shell is first started private final ArrayList<Pair<String, Runnable>> mInitCallbacks = new ArrayList<>(); private boolean mHasInitialized; - public ShellInitImpl( + public ShellInit( + ShellController shellController, DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, @@ -91,8 +93,9 @@ public class ShellInitImpl { FullscreenTaskListener fullscreenTaskListener, Optional<UnfoldAnimationController> unfoldAnimationController, Optional<UnfoldTransitionHandler> unfoldTransitionHandler, - Optional<FreeformTaskListener<?>> freeformTaskListenerOptional, + Optional<FreeformComponents> freeformComponentsOptional, Optional<RecentTasksController> recentTasks, + Optional<ActivityEmbeddingController> activityEmbeddingOptional, Transitions transitions, StartingWindowController startingWindow, ShellExecutor mainExecutor) { @@ -108,15 +111,14 @@ public class ShellInitImpl { mPipTouchHandlerOptional = pipTouchHandlerOptional; mUnfoldController = unfoldAnimationController; mUnfoldTransitionHandler = unfoldTransitionHandler; - mFreeformTaskListenerOptional = freeformTaskListenerOptional; + mFreeformComponentsOptional = freeformComponentsOptional; mRecentTasks = recentTasks; + mActivityEmbeddingOptional = activityEmbeddingOptional; mTransitions = transitions; mMainExecutor = mainExecutor; mStartingWindow = startingWindow; - } - - public ShellInit asShellInit() { - return mImpl; + // TODO(238217847): To be removed once the init dependencies are inverted + shellController.setShellInit(this); } private void legacyInit() { @@ -139,7 +141,10 @@ public class ShellInitImpl { if (Transitions.ENABLE_SHELL_TRANSITIONS) { mTransitions.register(mShellTaskOrganizer); + mActivityEmbeddingOptional.ifPresent(ActivityEmbeddingController::init); mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init); + mFreeformComponentsOptional.flatMap(f -> f.mTaskTransitionHandler) + .ifPresent(mTransitions::addHandler); if (mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) { final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions, mPipTouchHandlerOptional.get().getTransitionHandler(), @@ -155,9 +160,9 @@ public class ShellInitImpl { mPipTouchHandlerOptional.ifPresent((handler) -> handler.init()); // Initialize optional freeform - mFreeformTaskListenerOptional.ifPresent(f -> + mFreeformComponentsOptional.ifPresent(f -> mShellTaskOrganizer.addListenerForType( - f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM)); + f.mTaskListener, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM)); mUnfoldController.ifPresent(UnfoldAnimationController::init); mRecentTasks.ifPresent(RecentTasksController::init); @@ -205,16 +210,4 @@ public class ShellInitImpl { mHasInitialized = true; } - - @ExternalThread - private class InitImpl implements ShellInit { - @Override - public void init() { - try { - mMainExecutor.executeBlocking(ShellInitImpl.this::init); - } catch (InterruptedException e) { - throw new RuntimeException("Failed to initialize the Shell in 2s", e); - } - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java new file mode 100644 index 000000000000..254c253b0042 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInterface.java @@ -0,0 +1,62 @@ +/* + * 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.wm.shell.sysui; + +import android.content.res.Configuration; + +import java.io.PrintWriter; + +/** + * General interface for notifying the Shell of common SysUI events like configuration or keyguard + * changes. + */ +public interface ShellInterface { + + /** + * Initializes the shell state. + */ + default void onInit() {} + + /** + * Dumps the shell state. + */ + default void dump(PrintWriter pw) {} + + /** + * Handles a shell command. + */ + default boolean handleCommand(final String[] args, PrintWriter pw) { + return false; + } + + /** + * Notifies the Shell that the configuration has changed. + */ + default void onConfigurationChanged(Configuration newConfiguration) {} + + /** + * Notifies the Shell that the keyguard is showing (and if so, whether it is occluded) or not + * showing, and whether it is animating a dismiss. + */ + default void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) {} + + /** + * Notifies the Shell when the keyguard dismiss animation has finished. + */ + default void onKeyguardDismissAnimationFinished() {} +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java deleted file mode 100644 index ad9dda619370..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelper.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 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.wm.shell.tasksurfacehelper; - -import android.app.ActivityManager.RunningTaskInfo; -import android.graphics.Rect; -import android.view.SurfaceControl; - -import java.util.concurrent.Executor; -import java.util.function.Consumer; - -/** - * Interface to communicate with a Task's SurfaceControl. - */ -public interface TaskSurfaceHelper { - - /** Sets the METADATA_GAME_MODE for the layer corresponding to the task **/ - default void setGameModeForTask(int taskId, int gameMode) {} - - /** Takes a screenshot for a task **/ - default void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor, - Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {} -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java deleted file mode 100644 index 064d9d1231c1..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2021 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.wm.shell.tasksurfacehelper; - -import android.app.ActivityManager.RunningTaskInfo; -import android.graphics.Rect; -import android.view.SurfaceControl; - -import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.common.ShellExecutor; - -import java.util.concurrent.Executor; -import java.util.function.Consumer; - -/** - * Intermediary controller that communicates with {@link ShellTaskOrganizer} to send commands - * to SurfaceControl. - */ -public class TaskSurfaceHelperController { - - private final ShellTaskOrganizer mTaskOrganizer; - private final ShellExecutor mMainExecutor; - private final TaskSurfaceHelperImpl mImpl = new TaskSurfaceHelperImpl(); - - public TaskSurfaceHelperController(ShellTaskOrganizer taskOrganizer, - ShellExecutor mainExecutor) { - mTaskOrganizer = taskOrganizer; - mMainExecutor = mainExecutor; - } - - public TaskSurfaceHelper asTaskSurfaceHelper() { - return mImpl; - } - - /** - * Sends a Transaction to set the game mode metadata on the - * corresponding SurfaceControl - */ - public void setGameModeForTask(int taskId, int gameMode) { - mTaskOrganizer.setSurfaceMetadata(taskId, SurfaceControl.METADATA_GAME_MODE, gameMode); - } - - /** - * Take screenshot of the specified task. - */ - public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, - Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) { - mTaskOrganizer.screenshotTask(taskInfo, crop, consumer); - } - - private class TaskSurfaceHelperImpl implements TaskSurfaceHelper { - @Override - public void setGameModeForTask(int taskId, int gameMode) { - mMainExecutor.execute(() -> { - TaskSurfaceHelperController.this.setGameModeForTask(taskId, gameMode); - }); - } - - @Override - public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor, - Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) { - mMainExecutor.execute(() -> { - TaskSurfaceHelperController.this.screenshotTask(taskInfo, crop, - (t) -> executor.execute(() -> consumer.accept(t))); - }); - } - } -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index dcd6277966dd..0bec54399dd8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -483,11 +483,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { postStartTransactionCallbacks.add(t -> startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish, mTransactionPool, mMainExecutor, mAnimExecutor, - null /* position */, cornerRadius, clipRect)); + change.getEndRelOffset(), cornerRadius, clipRect)); } else { startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish, - mTransactionPool, mMainExecutor, mAnimExecutor, null /* position */, - cornerRadius, clipRect); + mTransactionPool, mMainExecutor, mAnimExecutor, + change.getEndRelOffset(), cornerRadius, clipRect); } if (info.getAnimationOptions() != null) { @@ -934,7 +934,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { a.restrictDuration(MAX_ANIMATION_DURATION); a.scaleCurrentDuration(mTransitionAnimationScaleSetting); startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool, - mMainExecutor, mAnimExecutor, new Point(bounds.left, bounds.top), + mMainExecutor, mAnimExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds()); } @@ -959,7 +959,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { a.restrictDuration(MAX_ANIMATION_DURATION); a.scaleCurrentDuration(mTransitionAnimationScaleSetting); startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool, - mMainExecutor, mAnimExecutor, null /* position */, + mMainExecutor, mAnimExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java index 46f73fda37a1..1005ef1705f0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java @@ -34,7 +34,6 @@ import android.annotation.NonNull; import android.content.Context; import android.graphics.Color; import android.graphics.ColorSpace; -import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Rect; import android.hardware.HardwareBuffer; @@ -85,8 +84,6 @@ class ScreenRotationAnimation { private final Context mContext; private final TransactionPool mTransactionPool; private final float[] mTmpFloats = new float[9]; - // Complete transformations being applied. - private final Matrix mSnapshotInitialMatrix = new Matrix(); /** The leash of display. */ private final SurfaceControl mSurfaceControl; private final Rect mStartBounds = new Rect(); @@ -169,16 +166,15 @@ class ScreenRotationAnimation { .setName("RotationLayer") .build(); - GraphicBuffer buffer = GraphicBuffer.createFromHardwareBuffer( - screenshotBuffer.getHardwareBuffer()); - t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.setPosition(mAnimLeash, 0, 0); t.setAlpha(mAnimLeash, 1); t.show(mAnimLeash); - t.setBuffer(mScreenshotLayer, buffer); - t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace()); + final ColorSpace colorSpace = screenshotBuffer.getColorSpace(); + final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); + t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace()); + t.setBuffer(mScreenshotLayer, hardwareBuffer); t.show(mScreenshotLayer); if (!isCustomRotate()) { @@ -189,8 +185,7 @@ class ScreenRotationAnimation { .setName("BackColorSurface") .build(); - HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); - mStartLuma = getMedianBorderLuma(hardwareBuffer, screenshotBuffer.getColorSpace()); + mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace); t.setLayer(mBackColorSurface, -1); t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma}); @@ -202,7 +197,7 @@ class ScreenRotationAnimation { Slog.w(TAG, "Unable to allocate freeze surface", e); } - setRotation(t); + setScreenshotTransform(t); t.apply(); } @@ -210,19 +205,36 @@ class ScreenRotationAnimation { return mAnimHint == ROTATION_ANIMATION_CROSSFADE || mAnimHint == ROTATION_ANIMATION_JUMPCUT; } - private void setRotation(SurfaceControl.Transaction t) { - // Compute the transformation matrix that must be applied - // to the snapshot to make it stay in the same original position - // with the current screen rotation. - int delta = deltaRotation(mEndRotation, mStartRotation); - createRotationMatrix(delta, mStartWidth, mStartHeight, mSnapshotInitialMatrix); - setRotationTransform(t, mSnapshotInitialMatrix); - } - - private void setRotationTransform(SurfaceControl.Transaction t, Matrix matrix) { + private void setScreenshotTransform(SurfaceControl.Transaction t) { if (mScreenshotLayer == null) { return; } + final Matrix matrix = new Matrix(); + final int delta = deltaRotation(mEndRotation, mStartRotation); + if (delta != 0) { + // Compute the transformation matrix that must be applied to the snapshot to make it + // stay in the same original position with the current screen rotation. + switch (delta) { + case Surface.ROTATION_90: + matrix.setRotate(90, 0, 0); + matrix.postTranslate(mStartHeight, 0); + break; + case Surface.ROTATION_180: + matrix.setRotate(180, 0, 0); + matrix.postTranslate(mStartWidth, mStartHeight); + break; + case Surface.ROTATION_270: + matrix.setRotate(270, 0, 0); + matrix.postTranslate(0, mStartWidth); + break; + } + } else if ((mEndWidth > mStartWidth) == (mEndHeight > mStartHeight) + && (mEndWidth != mStartWidth || mEndHeight != mStartHeight)) { + // Display resizes without rotation change. + final float scale = Math.max((float) mEndWidth / mStartHeight, + (float) mEndHeight / mStartHeight); + matrix.setScale(scale, scale); + } matrix.getValues(mTmpFloats); float x = mTmpFloats[Matrix.MTRANS_X]; float y = mTmpFloats[Matrix.MTRANS_Y]; @@ -230,9 +242,7 @@ class ScreenRotationAnimation { t.setMatrix(mScreenshotLayer, mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); - t.setAlpha(mScreenshotLayer, (float) 1.0); - t.show(mScreenshotLayer); } /** @@ -486,27 +496,6 @@ class ScreenRotationAnimation { return getMedianBorderLuma(buffer.getHardwareBuffer(), buffer.getColorSpace()); } - private static void createRotationMatrix(int rotation, int width, int height, - Matrix outMatrix) { - switch (rotation) { - case Surface.ROTATION_0: - outMatrix.reset(); - break; - case Surface.ROTATION_90: - outMatrix.setRotate(90, 0, 0); - outMatrix.postTranslate(height, 0); - break; - case Surface.ROTATION_180: - outMatrix.setRotate(180, 0, 0); - outMatrix.postTranslate(width, height); - break; - case Surface.ROTATION_270: - outMatrix.setRotate(270, 0, 0); - outMatrix.postTranslate(0, width); - break; - } - } - private static void applyColor(int startColor, int endColor, float[] rgbFloat, float fraction, SurfaceControl surface, SurfaceControl.Transaction t) { final int color = (Integer) ArgbEvaluator.getInstance().evaluate(fraction, startColor, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index fa22c7ca94d2..8e36154d10e7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -98,6 +98,12 @@ public class Transitions implements RemoteCallable<Transitions> { /** Transition type for dismissing split-screen. */ public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 7; + /** Transition type for freeform to maximize transition. */ + public static final int TRANSIT_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 8; + + /** Transition type for maximize to freeform transition. */ + public static final int TRANSIT_RESTORE_FROM_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 9; + private final WindowOrganizer mOrganizer; private final Context mContext; private final ShellExecutor mMainExecutor; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index 6d28d73996f0..08d6c50f94b4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -25,6 +25,7 @@ import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.content.Context; import android.os.Handler; +import android.view.Choreographer; import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.View; @@ -35,6 +36,8 @@ import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; +import com.android.wm.shell.transition.Transitions; /** * View model for the window decoration with a caption and shadows. Works with @@ -45,17 +48,22 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; private final Handler mMainHandler; + private final Choreographer mMainChoreographer; private final DisplayController mDisplayController; private final SyncTransactionQueue mSyncQueue; + private FreeformTaskTransitionStarter mTransitionStarter; + public CaptionWindowDecorViewModel( Context context, Handler mainHandler, + Choreographer mainChoreographer, ShellTaskOrganizer taskOrganizer, DisplayController displayController, SyncTransactionQueue syncQueue) { mContext = context; mMainHandler = mainHandler; + mMainChoreographer = mainChoreographer; mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class); mTaskOrganizer = taskOrganizer; mDisplayController = displayController; @@ -63,8 +71,16 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption } @Override + public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) { + mTransitionStarter = transitionStarter; + } + + @Override public CaptionWindowDecoration createWindowDecoration( - ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface) { + ActivityManager.RunningTaskInfo taskInfo, + SurfaceControl taskSurface, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration( mContext, mDisplayController, @@ -72,24 +88,46 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption taskInfo, taskSurface, mMainHandler, + mMainChoreographer, mSyncQueue); TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration); CaptionTouchEventListener touchEventListener = new CaptionTouchEventListener(taskInfo, taskPositioner); windowDecoration.setCaptionListeners(touchEventListener, touchEventListener); windowDecoration.setDragResizeCallback(taskPositioner); - onTaskInfoChanged(taskInfo, windowDecoration); + setupWindowDecorationForTransition(taskInfo, startT, finishT, windowDecoration); + setupCaptionColor(taskInfo, windowDecoration); return windowDecoration; } @Override + public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) { + return (windowDecor instanceof CaptionWindowDecoration) + ? (CaptionWindowDecoration) windowDecor + : null; + } + + @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) { decoration.relayout(taskInfo); + setupCaptionColor(taskInfo, decoration); + } + + private void setupCaptionColor(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) { int statusBarColor = taskInfo.taskDescription.getStatusBarColor(); decoration.setCaptionColor(statusBarColor); } + @Override + public void setupWindowDecorationForTransition( + RunningTaskInfo taskInfo, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT, + CaptionWindowDecoration decoration) { + decoration.relayout(taskInfo, startT, finishT); + } + private class CaptionTouchEventListener implements View.OnClickListener, View.OnTouchListener { @@ -100,7 +138,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption private int mDragPointerId = -1; private CaptionTouchEventListener( - RunningTaskInfo taskInfo, DragResizeCallback dragResizeCallback) { + RunningTaskInfo taskInfo, + DragResizeCallback dragResizeCallback) { mTaskId = taskInfo.taskId; mTaskToken = taskInfo.token; mDragResizeCallback = dragResizeCallback; @@ -108,7 +147,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption @Override public void onClick(View v) { - int id = v.getId(); + final int id = v.getId(); if (id == R.id.close_window) { mActivityTaskManager.removeTask(mTaskId); } else if (id == R.id.maximize_window) { @@ -124,7 +163,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) { wct.setBounds(mTaskToken, null); } - mSyncQueue.queue(wct); + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + mTransitionStarter.startWindowingModeTransition(targetWindowingMode, wct); + } else { + mSyncQueue.queue(wct); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java index cdca051a4ee5..dc212fc2ab4d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java @@ -25,6 +25,7 @@ import android.graphics.Rect; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.VectorDrawable; import android.os.Handler; +import android.view.Choreographer; import android.view.SurfaceControl; import android.view.View; import android.window.WindowContainerTransaction; @@ -59,6 +60,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL RESIZE_HANDLE_IN_DIP, RESIZE_HANDLE_IN_DIP, RESIZE_HANDLE_IN_DIP, RESIZE_HANDLE_IN_DIP); private final Handler mHandler; + private final Choreographer mChoreographer; private final SyncTransactionQueue mSyncQueue; private View.OnClickListener mOnCaptionButtonClickListener; @@ -77,10 +79,12 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, Handler handler, + Choreographer choreographer, SyncTransactionQueue syncQueue) { super(context, displayController, taskOrganizer, taskInfo, taskSurface); mHandler = handler; + mChoreographer = choreographer; mSyncQueue = syncQueue; } @@ -97,6 +101,16 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { + final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + relayout(taskInfo, t, t); + mSyncQueue.runInSync(transaction -> { + transaction.merge(t); + t.close(); + }); + } + + void relayout(ActivityManager.RunningTaskInfo taskInfo, + SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { final int shadowRadiusDp = taskInfo.isFocused ? DECOR_SHADOW_FOCUSED_THICKNESS_IN_DIP : DECOR_SHADOW_UNFOCUSED_THICKNESS_IN_DIP; final boolean isFreeform = mTaskInfo.configuration.windowConfiguration.getWindowingMode() @@ -106,18 +120,12 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; - final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); final WindowContainerTransaction wct = new WindowContainerTransaction(); relayout(taskInfo, R.layout.caption_window_decoration, oldRootView, - DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, t, wct, mResult); + DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, startT, finishT, wct, mResult); taskInfo = null; // Clear it just in case we use it accidentally - mSyncQueue.runInSync(transaction -> { - transaction.merge(t); - t.close(); - - mTaskOrganizer.applyTransaction(wct); - }); + mTaskOrganizer.applyTransaction(wct); if (mResult.mRootView == null) { // This means something blocks the window decor from showing, e.g. the task is hidden. @@ -138,6 +146,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL mDragResizeListener = new DragResizeInputListener( mContext, mHandler, + mChoreographer, mDisplay.getDisplayId(), mDecorationContainerSurface, mDragResizeCallback); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java index c6bbb027c8e6..f512b0d4fe10 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java @@ -27,8 +27,8 @@ import android.hardware.input.InputManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.RemoteException; +import android.view.Choreographer; import android.view.IWindowSession; import android.view.InputChannel; import android.view.InputEvent; @@ -49,6 +49,7 @@ class DragResizeInputListener implements AutoCloseable { private final IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession(); private final Handler mHandler; + private final Choreographer mChoreographer; private final InputManager mInputManager; private final int mDisplayId; @@ -68,11 +69,13 @@ class DragResizeInputListener implements AutoCloseable { DragResizeInputListener( Context context, Handler handler, + Choreographer choreographer, int displayId, SurfaceControl decorationSurface, DragResizeCallback callback) { mInputManager = context.getSystemService(InputManager.class); mHandler = handler; + mChoreographer = choreographer; mDisplayId = displayId; mDecorationSurface = decorationSurface; // Use a fake window as the backing surface is a container layer and we don't want to create @@ -97,7 +100,8 @@ class DragResizeInputListener implements AutoCloseable { e.rethrowFromSystemServer(); } - mInputEventReceiver = new TaskResizeInputEventReceiver(mInputChannel, mHandler.getLooper()); + mInputEventReceiver = new TaskResizeInputEventReceiver( + mInputChannel, mHandler, mChoreographer); mCallback = callback; } @@ -154,10 +158,6 @@ class DragResizeInputListener implements AutoCloseable { } catch (RemoteException e) { e.rethrowFromSystemServer(); } - - // This marks all relevant components have handled the previous resize event and can take - // the next one now. - mInputEventReceiver.onHandledLastResizeEvent(); } @Override @@ -171,28 +171,39 @@ class DragResizeInputListener implements AutoCloseable { } private class TaskResizeInputEventReceiver extends InputEventReceiver { - private boolean mWaitingForLastResizeEventHandled; + private final Choreographer mChoreographer; + private final Runnable mConsumeBatchEventRunnable; + private boolean mConsumeBatchEventScheduled; - private TaskResizeInputEventReceiver(InputChannel inputChannel, Looper looper) { - super(inputChannel, looper); - } + private TaskResizeInputEventReceiver( + InputChannel inputChannel, Handler handler, Choreographer choreographer) { + super(inputChannel, handler.getLooper()); + mChoreographer = choreographer; - private void onHandledLastResizeEvent() { - mWaitingForLastResizeEventHandled = false; - consumeBatchedInputEvents(-1); + mConsumeBatchEventRunnable = () -> { + mConsumeBatchEventScheduled = false; + if (consumeBatchedInputEvents(mChoreographer.getFrameTimeNanos())) { + // If we consumed a batch here, we want to go ahead and schedule the + // consumption of batched input events on the next frame. Otherwise, we would + // wait until we have more input events pending and might get starved by other + // things occurring in the process. + scheduleConsumeBatchEvent(); + } + }; } @Override public void onBatchedInputEventPending(int source) { - // InputEventReceiver keeps continuous move events in a batched event until explicitly - // consuming it or an incompatible event shows up (likely an up event in this case). We - // continue to keep move events in the next batched event until we receive a geometry - // update so that we don't put too much pressure on the framework with excessive number - // of input events if it can't handle them fast enough. It's more responsive to always - // resize the task to the latest received coordinates. - if (!mWaitingForLastResizeEventHandled) { - consumeBatchedInputEvents(-1); + scheduleConsumeBatchEvent(); + } + + private void scheduleConsumeBatchEvent() { + if (mConsumeBatchEventScheduled) { + return; } + mChoreographer.postCallback( + Choreographer.CALLBACK_INPUT, mConsumeBatchEventRunnable, null); + mConsumeBatchEventScheduled = true; } @Override @@ -211,14 +222,12 @@ class DragResizeInputListener implements AutoCloseable { mDragPointerId = e.getPointerId(0); mCallback.onDragResizeStart( calculateCtrlType(e.getX(0), e.getY(0)), e.getRawX(0), e.getRawY(0)); - mWaitingForLastResizeEventHandled = false; break; } case MotionEvent.ACTION_MOVE: { int dragPointerIndex = e.findPointerIndex(mDragPointerId); mCallback.onDragResizeMove( e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex)); - mWaitingForLastResizeEventHandled = true; break; } case MotionEvent.ACTION_UP: @@ -226,7 +235,6 @@ class DragResizeInputListener implements AutoCloseable { int dragPointerIndex = e.findPointerIndex(mDragPointerId); mCallback.onDragResizeEnd( e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex)); - mWaitingForLastResizeEventHandled = false; mDragPointerId = -1; break; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java index 6f9ceff722ac..c234949572bf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java @@ -19,6 +19,10 @@ package com.android.wm.shell.windowdecor; import android.app.ActivityManager; import android.view.SurfaceControl; +import androidx.annotation.Nullable; + +import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; + /** * The interface used by some {@link com.android.wm.shell.ShellTaskOrganizer.TaskListener} to help * customize {@link WindowDecoration}. Its implementations are responsible to interpret user's @@ -30,13 +34,34 @@ import android.view.SurfaceControl; public interface WindowDecorViewModel<T extends AutoCloseable> { /** + * Sets the transition starter that starts freeform task transitions. + * + * @param transitionStarter the transition starter that starts freeform task transitions + */ + void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter); + + /** * Creates a window decoration for the given task. * * @param taskInfo the initial task info of the task * @param taskSurface the surface of the task + * @param startT the start transaction to be applied before the transition + * @param finishT the finish transaction to restore states after the transition * @return the window decoration object */ - T createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface); + T createWindowDecoration( + ActivityManager.RunningTaskInfo taskInfo, + SurfaceControl taskSurface, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT); + + /** + * Adopts the window decoration if possible. + * + * @param windowDecor the potential window decoration to adopt + * @return the window decoration if it can be adopted, or {@code null} otherwise. + */ + T adoptWindowDecoration(@Nullable AutoCloseable windowDecor); /** * Notifies a task info update on the given task, with the window decoration created previously @@ -46,4 +71,18 @@ public interface WindowDecorViewModel<T extends AutoCloseable> { * @param windowDecoration the window decoration created for the task */ void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo, T windowDecoration); + + /** + * Notifies a transition is about to start about the given task to give the window decoration a + * chance to prepare for this transition. + * + * @param startT the start transaction to be applied before the transition + * @param finishT the finish transaction to restore states after the transition + * @param windowDecoration the window decoration created for the task + */ + void setupWindowDecorationForTransition( + ActivityManager.RunningTaskInfo taskInfo, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT, + T windowDecoration); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index c19a33abf8a4..4380bdc36417 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -140,8 +140,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> abstract void relayout(RunningTaskInfo taskInfo); void relayout(RunningTaskInfo taskInfo, int layoutResId, T rootView, float captionHeightDp, - Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction t, - WindowContainerTransaction wct, RelayoutResult<T> outResult) { + Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT, WindowContainerTransaction wct, + RelayoutResult<T> outResult) { outResult.reset(); final Configuration oldTaskConfig = mTaskInfo.getConfiguration(); @@ -151,7 +152,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> if (!mTaskInfo.isVisible) { releaseViews(); - t.hide(mTaskSurface); + finishT.hide(mTaskSurface); return; } @@ -192,7 +193,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .setParent(mTaskSurface) .build(); - t.setTrustedOverlay(mDecorationContainerSurface, true); + startT.setTrustedOverlay(mDecorationContainerSurface, true); } final Rect taskBounds = taskConfig.windowConfiguration.getBounds(); @@ -205,7 +206,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> outResult.mHeight = taskBounds.height() + (int) (outsetsDp.bottom * outResult.mDensity) - decorContainerOffsetY; - t.setPosition(mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY) + startT.setPosition( + mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY) .setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight) .setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1) .show(mDecorationContainerSurface); @@ -222,10 +224,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> float shadowRadius = outResult.mDensity * shadowRadiusDp; int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor(); - mTmpColor[0] = Color.red(backgroundColorInt); - mTmpColor[1] = Color.green(backgroundColorInt); - mTmpColor[2] = Color.blue(backgroundColorInt); - t.setCrop(mTaskBackgroundSurface, taskBounds) + mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f; + mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f; + mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f; + startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height()) .setShadowRadius(mTaskBackgroundSurface, shadowRadius) .setColor(mTaskBackgroundSurface, mTmpColor); @@ -264,9 +266,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> decorContainerOffsetY, outResult.mWidth + decorContainerOffsetX, outResult.mHeight + decorContainerOffsetY); - t.setPosition(mTaskSurface, taskPosition.x, taskPosition.y) - .setCrop(mTaskSurface, mTaskSurfaceCrop) - .show(mTaskSurface); + startT.show(mTaskSurface); + finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y) + .setCrop(mTaskSurface, mTaskSurfaceCrop); } /** diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt index 70771d842197..1c587a2078cf 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker import android.app.Instrumentation +import android.platform.test.annotations.Presubmit import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.tapl.LauncherInstrumentation import com.android.server.wm.flicker.FlickerBuilderProvider @@ -34,6 +35,7 @@ import com.android.server.wm.flicker.taskBarWindowIsAlwaysVisible import com.android.server.wm.traces.common.ComponentMatcher import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper import org.junit.Assume +import org.junit.Test /** * Base test class containing common assertions for [ComponentMatcher.NAV_BAR], @@ -80,6 +82,8 @@ abstract class BaseTest @JvmOverloads constructor( /** * Checks that the [ComponentMatcher.NAV_BAR] layer is visible during the whole transition */ + @Presubmit + @Test open fun navBarLayerIsVisibleAtStartAndEnd() { Assume.assumeFalse(testSpec.isTablet) testSpec.navBarLayerIsVisibleAtStartAndEnd() @@ -88,6 +92,8 @@ abstract class BaseTest @JvmOverloads constructor( /** * Checks the position of the [ComponentMatcher.NAV_BAR] at the start and end of the transition */ + @Presubmit + @Test open fun navBarLayerPositionAtStartAndEnd() { Assume.assumeFalse(testSpec.isTablet) testSpec.navBarLayerPositionAtStartAndEnd() @@ -98,6 +104,8 @@ abstract class BaseTest @JvmOverloads constructor( * * Note: Phones only */ + @Presubmit + @Test open fun navBarWindowIsAlwaysVisible() { Assume.assumeFalse(testSpec.isTablet) testSpec.navBarWindowIsAlwaysVisible() @@ -106,6 +114,8 @@ abstract class BaseTest @JvmOverloads constructor( /** * Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition */ + @Presubmit + @Test open fun taskBarLayerIsVisibleAtStartAndEnd() { Assume.assumeTrue(testSpec.isTablet) testSpec.taskBarLayerIsVisibleAtStartAndEnd() @@ -116,6 +126,8 @@ abstract class BaseTest @JvmOverloads constructor( * * Note: Large screen only */ + @Presubmit + @Test open fun taskBarWindowIsAlwaysVisible() { Assume.assumeTrue(testSpec.isTablet) testSpec.taskBarWindowIsAlwaysVisible() @@ -124,25 +136,31 @@ abstract class BaseTest @JvmOverloads constructor( /** * Checks that the [ComponentMatcher.STATUS_BAR] layer is visible during the whole transition */ + @Presubmit + @Test open fun statusBarLayerIsVisibleAtStartAndEnd() = testSpec.statusBarLayerIsVisibleAtStartAndEnd() /** * Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the transition */ + @Presubmit + @Test open fun statusBarLayerPositionAtStartAndEnd() = testSpec.statusBarLayerPositionAtStartAndEnd() /** * Checks that the [ComponentMatcher.STATUS_BAR] window is visible during the whole transition */ - open fun statusBarWindowIsAlwaysVisible() { - testSpec.statusBarWindowIsAlwaysVisible() - } + @Presubmit + @Test + open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible() /** * Checks that all layers that are visible on the trace, are visible for at least 2 * consecutive entries. */ + @Presubmit + @Test open fun visibleLayersShownMoreThanOneConsecutiveEntry() { testSpec.assertLayers { this.visibleLayersShownMoreThanOneConsecutiveEntry() @@ -153,6 +171,8 @@ abstract class BaseTest @JvmOverloads constructor( * Checks that all windows that are visible on the trace, are visible for at least 2 * consecutive entries. */ + @Presubmit + @Test open fun visibleWindowsShownMoreThanOneConsecutiveEntry() { testSpec.assertWm { this.visibleWindowsShownMoreThanOneConsecutiveEntry() diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt index 319de8e4e310..293eb7cd5581 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt @@ -101,6 +101,12 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr } /** {@inheritDoc} */ + @FlakyTest + @Test + override fun visibleLayersShownMoreThanOneConsecutiveEntry() = + super.visibleLayersShownMoreThanOneConsecutiveEntry() + + /** {@inheritDoc} */ @FlakyTest(bugId = 206753786) @Test override fun navBarLayerIsVisibleAtStartAndEnd() = diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt index a558450f4ed8..1950e486f34b 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt @@ -75,7 +75,7 @@ open class MultiBubblesScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen Until.findObjects( By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME) ), FIND_OBJECT_TIMEOUT - ) + ) ?: error("No bubbles found") for (entry in bubbles) { entry?.run { entry.click() } ?: error("Bubble not found") SystemClock.sleep(1000) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt index 07731f85193a..42aac573ca9e 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt @@ -16,13 +16,18 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.FlakyTest +import android.platform.test.annotations.Postsubmit +import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import org.junit.Assume import org.junit.FixMethodOrder +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized @@ -72,6 +77,8 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest } } + @Postsubmit + @Test override fun pipAppLayerAlwaysVisible() { if (!testSpec.isGesturalNavigation) super.pipAppLayerAlwaysVisible() else { // pip layer in gesture nav will disappear during transition @@ -83,18 +90,43 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest } } + @Postsubmit + @Test override fun pipLayerReduces() { // in gestural nav the pip enters through alpha animation Assume.assumeFalse(testSpec.isGesturalNavigation) super.pipLayerReduces() } + @Postsubmit + @Test override fun focusChanges() { // in gestural nav the focus goes to different activity on swipe up Assume.assumeFalse(testSpec.isGesturalNavigation) super.focusChanges() } + /** {@inheritDoc} */ + @Postsubmit + @Test + override fun pipAppWindowAlwaysVisible() = super.pipAppWindowAlwaysVisible() + + @Presubmit + @Test + override fun entireScreenCovered() { + Assume.assumeFalse(isShellTransitionsEnabled) + super.entireScreenCovered() + } + + @FlakyTest(bugId = 227313015) + @Test + fun entireScreenCovered_ShellTransit() { + Assume.assumeTrue(isShellTransitionsEnabled) + super.entireScreenCovered() + } + + @Postsubmit + @Test override fun pipLayerRemainInsideVisibleBounds() { if (!testSpec.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds() else { // pip layer in gesture nav will disappear during transition diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt index 25b1dd901b6b..045022414fe0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt @@ -16,7 +16,7 @@ package com.android.wm.shell.flicker.pip -import android.platform.test.annotations.Postsubmit +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice @@ -80,7 +80,7 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec */ @Presubmit @Test - fun pipAppWindowAlwaysVisible() { + open fun pipAppWindowAlwaysVisible() { testSpec.assertWm { this.isAppWindowVisible(pipApp) } @@ -89,7 +89,7 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec /** * Checks [pipApp] layer remains visible throughout the animation */ - @Presubmit + @FlakyTest(bugId = 239807171) @Test open fun pipAppLayerAlwaysVisible() { testSpec.assertLayers { @@ -113,7 +113,7 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec * Checks that the pip app layer remains inside the display bounds throughout the whole * animation */ - @Presubmit + @FlakyTest(bugId = 239807171) @Test open fun pipLayerRemainInsideVisibleBounds() { testSpec.assertLayersVisibleRegion(pipApp) { @@ -173,65 +173,6 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec } } - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = - super.statusBarLayerPositionAtStartAndEnd() - companion object { /** * Creates the test configurations. diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt index f486f257e679..dff447b97b9b 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt @@ -227,57 +227,14 @@ class EnterPipToOtherOrientationTest( /** {@inheritDoc} */ @Postsubmit @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test override fun visibleLayersShownMoreThanOneConsecutiveEntry() = super.visibleLayersShownMoreThanOneConsecutiveEntry() /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 197726599) + @FlakyTest(bugId = 227313015) @Test override fun entireScreenCovered() = super.entireScreenCovered() - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = - super.statusBarLayerPositionAtStartAndEnd() - companion object { /** * Creates the test configurations. diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt index 6a86a14070bb..45851c8b6326 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.pip -import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import com.android.server.wm.flicker.FlickerTestParameter import com.android.wm.shell.flicker.helpers.FixedAppHelper @@ -129,61 +128,7 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans } /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit + @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = - super.statusBarLayerPositionAtStartAndEnd() } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt index 774dbfe2a9dd..b5a3c78b67a7 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.FlakyTest import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory @@ -78,6 +79,16 @@ class ExitPipViaExpandButtonClickTest( } } + /** {@inheritDoc} */ + @FlakyTest(bugId = 227313015) + @Test + override fun entireScreenCovered() = super.entireScreenCovered() + + /** {@inheritDoc} */ + @FlakyTest(bugId = 197726610) + @Test + override fun pipLayerExpands() = super.pipLayerExpands() + companion object { /** * Creates the test configurations. diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt index 685f4584c92c..1d266140f2e6 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt @@ -109,6 +109,11 @@ class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransit super.pipLayerExpands() } + /** {@inheritDoc} */ + @FlakyTest(bugId = 227313015) + @Test + override fun entireScreenCovered() = super.entireScreenCovered() + companion object { /** * Creates the test configurations. diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt index 430d5ae35162..1c0bd0caa901 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice @@ -167,65 +166,6 @@ class ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition } } - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = - super.statusBarLayerPositionAtStartAndEnd() - companion object { /** * Creates the test configurations. diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt index 895158b4812c..9fb941e2a584 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.pip -import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.traces.region.RegionSubject @@ -110,63 +109,4 @@ abstract class MovePipShelfHeightTransition( } } } - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerPositionAtStartAndEnd() = - super.statusBarLayerPositionAtStartAndEnd() } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt index 3d9950aa3240..911d402cfde7 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice @@ -110,59 +109,6 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS } } - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = - super.visibleWindowsShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun entireScreenCovered() = super.entireScreenCovered() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun statusBarLayerIsVisibleAtStartAndEnd() = - super.statusBarLayerIsVisibleAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() - - /** {@inheritDoc} */ - @Postsubmit - @Test - override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd() - companion object { private const val TAG_IME_VISIBLE = "imeIsVisible" diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt index 3326802dfe37..09248a167308 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory @@ -27,8 +26,11 @@ import com.android.server.wm.flicker.annotation.Group4 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.entireScreenCovered import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.helpers.setRotation import com.android.wm.shell.flicker.helpers.FixedAppHelper +import org.junit.Assume +import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -64,6 +66,11 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.startRotation) private val screenBoundsEnd = WindowUtils.getDisplayBounds(testSpec.endRotation) + @Before + open fun before() { + Assume.assumeFalse(isShellTransitionsEnabled) + } + override val transition: FlickerBuilder.() -> Unit get() = buildTransition(eachRun = false) { setup { @@ -82,36 +89,60 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS /** * Checks that all parts of the screen are covered at the start and end of the transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test override fun entireScreenCovered() = testSpec.entireScreenCovered() /** * Checks the position of the navigation bar at the start and end of the transition */ - @FlakyTest + @FlakyTest(bugId = 240499181) @Test override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd() /** * Checks that [fixedApp] layer is within [screenBoundsStart] at the start of the transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test - fun appLayerRotates_StartingBounds() { + fun fixedAppLayer_StartingBounds() { testSpec.assertLayersStart { - visibleRegion(fixedApp).coversExactly(screenBoundsStart) + visibleRegion(fixedApp).coversAtMost(screenBoundsStart) } } /** * Checks that [fixedApp] layer is within [screenBoundsEnd] at the end of the transition */ - @Presubmit + @FlakyTest(bugId = 240499181) + @Test + fun fixedAppLayer_EndingBounds() { + testSpec.assertLayersEnd { + visibleRegion(fixedApp).coversAtMost(screenBoundsEnd) + } + } + + /** + * Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the start + * of the transition + */ + @FlakyTest(bugId = 240499181) + @Test + fun appLayers_StartingBounds() { + testSpec.assertLayersStart { + visibleRegion(fixedApp.or(pipApp)).coversExactly(screenBoundsStart) + } + } + + /** + * Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the end + * of the transition + */ + @FlakyTest(bugId = 240499181) @Test - fun appLayerRotates_EndingBounds() { + fun appLayers_EndingBounds() { testSpec.assertLayersEnd { - visibleRegion(fixedApp).coversExactly(screenBoundsEnd) + visibleRegion(fixedApp.or(pipApp)).coversExactly(screenBoundsEnd) } } @@ -127,7 +158,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS /** * Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test fun pipLayerRotates_StartingBounds() { pipLayerRotates_StartingBounds_internal() @@ -136,7 +167,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS /** * Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test fun pipLayerRotates_EndingBounds() { testSpec.assertLayersEnd { @@ -148,7 +179,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS * Ensure that the [pipApp] window does not obscure the [fixedApp] at the start of the * transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test fun pipIsAboveFixedAppWindow_Start() { testSpec.assertWmStart { @@ -160,7 +191,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS * Ensure that the [pipApp] window does not obscure the [fixedApp] at the end of the * transition */ - @Presubmit + @FlakyTest(bugId = 240499181) @Test fun pipIsAboveFixedAppWindow_End() { testSpec.assertWmEnd { @@ -168,6 +199,60 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS } } + @FlakyTest(bugId = 240499181) + @Test + override fun navBarLayerIsVisibleAtStartAndEnd() { + super.navBarLayerIsVisibleAtStartAndEnd() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun navBarWindowIsAlwaysVisible() { + super.navBarWindowIsAlwaysVisible() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun statusBarLayerIsVisibleAtStartAndEnd() { + super.statusBarLayerIsVisibleAtStartAndEnd() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun statusBarLayerPositionAtStartAndEnd() { + super.statusBarLayerPositionAtStartAndEnd() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun statusBarWindowIsAlwaysVisible() { + super.statusBarWindowIsAlwaysVisible() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun taskBarLayerIsVisibleAtStartAndEnd() { + super.taskBarLayerIsVisibleAtStartAndEnd() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun taskBarWindowIsAlwaysVisible() { + super.taskBarWindowIsAlwaysVisible() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun visibleLayersShownMoreThanOneConsecutiveEntry() { + super.visibleLayersShownMoreThanOneConsecutiveEntry() + } + + @FlakyTest(bugId = 240499181) + @Test + override fun visibleWindowsShownMoreThanOneConsecutiveEntry() { + super.visibleWindowsShownMoreThanOneConsecutiveEntry() + } + companion object { /** * Creates the test configurations. @@ -180,7 +265,8 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS fun getParams(): Collection<FlickerTestParameter> { return FlickerTestParameterFactory.getInstance().getConfigRotationTests( supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90), - repetitions = 3) + repetitions = 3 + ) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt new file mode 100644 index 000000000000..0dd38cdf4681 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.pip + +import android.platform.test.annotations.FlakyTest +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.FlickerParametersRunnerFactory +import com.android.server.wm.flicker.FlickerTestParameter +import com.android.server.wm.flicker.annotation.Group4 +import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled +import org.junit.Assume +import org.junit.Before +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test Pip Stack in bounds after rotations. + * + * To run this test: `atest WMShellFlickerTests:PipRotationTest_ShellTransit` + * + * Actions: + * Launch a [pipApp] in pip mode + * Launch another app [fixedApp] (appears below pip) + * Rotate the screen from [testSpec.startRotation] to [testSpec.endRotation] + * (usually, 0->90 and 90->0) + * + * Notes: + * 1. Some default assertions (e.g., nav bar, status bar and screen covered) + * are inherited from [PipTransition] + * 2. Part of the test setup occurs automatically via + * [com.android.server.wm.flicker.TransitionRunnerWithRules], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + */ +@RequiresDevice +@RunWith(Parameterized::class) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Group4 +@FlakyTest(bugId = 239575053) +class PipRotationTest_ShellTransit(testSpec: FlickerTestParameter) : PipRotationTest(testSpec) { + @Before + override fun before() { + Assume.assumeTrue(isShellTransitionsEnabled) + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java index 49228720b81d..f8b3fb3def62 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java @@ -34,13 +34,12 @@ public class MockSurfaceControlHelper { * given {@link SurfaceControl} when calling {@link SurfaceControl.Builder#build()}. * * @param mockSurfaceControl the first {@link SurfaceControl} to return - * @param mockSurfaceControls following {@link SurfaceControl} to return * @return the mock of {@link SurfaceControl.Builder} */ public static SurfaceControl.Builder createMockSurfaceControlBuilder( - SurfaceControl mockSurfaceControl, SurfaceControl... mockSurfaceControls) { + SurfaceControl mockSurfaceControl) { final SurfaceControl.Builder mockBuilder = mock(SurfaceControl.Builder.class, RETURNS_SELF); - doReturn(mockSurfaceControl, (Object[]) mockSurfaceControls) + doReturn(mockSurfaceControl) .when(mockBuilder) .build(); return mockBuilder; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java index 1effc97a0de3..6cd5677db2c3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitImplTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java @@ -24,19 +24,22 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; +import com.android.wm.shell.activityembedding.ActivityEmbeddingController; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.draganddrop.DragAndDropController; -import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.fullscreen.FullscreenTaskListener; import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer; 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.startingsurface.StartingWindowController; +import com.android.wm.shell.sysui.ShellController; +import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.UnfoldAnimationController; import com.android.wm.shell.unfold.UnfoldTransitionHandler; @@ -53,8 +56,9 @@ import java.util.Optional; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) -public class ShellInitImplTest extends ShellTestCase { +public class ShellInitTest extends ShellTestCase { + @Mock private ShellController mShellController; @Mock private DisplayController mDisplayController; @Mock private DisplayImeController mDisplayImeController; @Mock private DisplayInsetsController mDisplayInsetsController; @@ -67,23 +71,24 @@ public class ShellInitImplTest extends ShellTestCase { @Mock private FullscreenTaskListener mFullscreenTaskListener; @Mock private Optional<UnfoldAnimationController> mUnfoldAnimationController; @Mock private Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler; - @Mock private Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional; + @Mock private Optional<FreeformComponents> mFreeformComponentsOptional; @Mock private Optional<RecentTasksController> mRecentTasks; + @Mock private Optional<ActivityEmbeddingController> mActivityEmbeddingController; @Mock private Transitions mTransitions; @Mock private StartingWindowController mStartingWindow; @Mock private ShellExecutor mMainExecutor; - private ShellInitImpl mImpl; + private ShellInit mImpl; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mImpl = new ShellInitImpl(mDisplayController, mDisplayImeController, + mImpl = new ShellInit(mShellController, mDisplayController, mDisplayImeController, mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer, mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional, mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController, - mUnfoldTransitionHandler, mFreeformTaskListenerOptional, mRecentTasks, mTransitions, - mStartingWindow, mMainExecutor); + mUnfoldTransitionHandler, mFreeformComponentsOptional, mRecentTasks, + mActivityEmbeddingController, mTransitions, mStartingWindow, mMainExecutor); } @Test 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 31e55e7116f0..ba81602054a8 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 @@ -20,6 +20,7 @@ import static android.window.BackNavigationInfo.KEY_TRIGGER_BACK; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; @@ -39,6 +40,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; import android.provider.Settings; @@ -121,24 +123,22 @@ public class BackAnimationControllerTest extends ShellTestCase { HardwareBuffer hardwareBuffer, int backType, IOnBackInvokedCallback onBackInvokedCallback) { - BackNavigationInfo navigationInfo = new BackNavigationInfo( - backType, - topAnimationTarget, - screenshotSurface, - hardwareBuffer, - new WindowConfiguration(), - new RemoteCallback((bundle) -> {}), - onBackInvokedCallback); - try { - doReturn(navigationInfo).when(mActivityTaskManager).startBackNavigation(anyBoolean()); - } catch (RemoteException ex) { - ex.rethrowFromSystemServer(); - } + BackNavigationInfo.Builder builder = new BackNavigationInfo.Builder() + .setType(backType) + .setDepartingAnimationTarget(topAnimationTarget) + .setScreenshotSurface(screenshotSurface) + .setScreenshotBuffer(hardwareBuffer) + .setTaskWindowConfiguration(new WindowConfiguration()) + .setOnBackNavigationDone(new RemoteCallback((bundle) -> {})) + .setOnBackInvokedCallback(onBackInvokedCallback); + + createNavigationInfo(builder); } private void createNavigationInfo(BackNavigationInfo.Builder builder) { try { - doReturn(builder.build()).when(mActivityTaskManager).startBackNavigation(anyBoolean()); + doReturn(builder.build()).when(mActivityTaskManager) + .startBackNavigation(anyBoolean(), any()); } catch (RemoteException ex) { ex.rethrowFromSystemServer(); } @@ -297,6 +297,34 @@ public class BackAnimationControllerTest extends ShellTestCase { verify(mIOnBackInvokedCallback).onBackStarted(); } + + @Test + public void cancelBackInvokeWhenLostFocus() throws RemoteException { + mController.setBackToLauncherCallback(mIOnBackInvokedCallback); + RemoteAnimationTarget animationTarget = createAnimationTarget(); + + createNavigationInfo(animationTarget, null, null, + BackNavigationInfo.TYPE_RETURN_TO_HOME, null); + + doMotionEvent(MotionEvent.ACTION_DOWN, 0); + // Check that back start and progress is dispatched when first move. + doMotionEvent(MotionEvent.ACTION_MOVE, 100); + verify(mIOnBackInvokedCallback).onBackStarted(); + + // Check that back invocation is dispatched. + mController.setTriggerBack(true); // Fake trigger back + + // In case the focus has been changed. + IBinder token = mock(IBinder.class); + mController.mFocusObserver.focusLost(token); + mShellExecutor.flushAll(); + verify(mIOnBackInvokedCallback).onBackCancelled(); + + // No more back invoke. + doMotionEvent(MotionEvent.ACTION_UP, 0); + verify(mIOnBackInvokedCallback, never()).onBackInvoked(); + } + private void doMotionEvent(int actionDown, int coordinate) { mController.onMotionEvent( coordinate, coordinate, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt index 0972cf2c032f..1636c5f73133 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubblePersistentRepositoryTest.kt @@ -25,6 +25,7 @@ import com.android.wm.shell.bubbles.storage.BubbleXmlHelperTest.Companion.sparse import junit.framework.Assert.assertEquals import junit.framework.Assert.assertNotNull import junit.framework.Assert.assertTrue +import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -61,6 +62,12 @@ class BubblePersistentRepositoryTest : ShellTestCase() { bubbles.put(1, user1Bubbles) } + @After + fun teardown() { + // Clean up the any persisted bubbles for the next run + repository.persistsToDisk(SparseArray()) + } + @Test fun testReadWriteOperation() { // Verify read before write doesn't cause FileNotFoundException @@ -71,4 +78,4 @@ class BubblePersistentRepositoryTest : ShellTestCase() { repository.persistsToDisk(bubbles) assertTrue(sparseArraysEqual(bubbles, repository.readFromDisk())) } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java index 587782cb79ad..5b691f231d85 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java @@ -122,7 +122,7 @@ public class DisplayImeControllerTest extends ShellTestCase { private InsetsSourceControl[] insetsSourceControl() { return new InsetsSourceControl[]{ new InsetsSourceControl( - ITYPE_IME, mock(SurfaceControl.class), new Point(0, 0), Insets.NONE) + ITYPE_IME, mock(SurfaceControl.class), false, new Point(0, 0), Insets.NONE) }; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java index 3ef3a1f6a3ad..4a7fd3d259da 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.content.ComponentName; import android.os.RemoteException; import android.util.SparseArray; import android.view.IDisplayWindowInsetsController; @@ -165,7 +166,7 @@ public class DisplayInsetsControllerTest extends ShellTestCase { int hideInsetsCount = 0; @Override - public void topFocusedWindowChanged(String packageName, + public void topFocusedWindowChanged(ComponentName component, InsetsVisibilities requestedVisibilities) { topFocusedWindowChangedCount++; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java index 596100dcdead..828c13ecfda6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java @@ -53,6 +53,7 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -78,6 +79,7 @@ public class CompatUIControllerTest extends ShellTestCase { private static final int TASK_ID = 12; private CompatUIController mController; + private @Mock ShellController mMockShellController; private @Mock DisplayController mMockDisplayController; private @Mock DisplayInsetsController mMockDisplayInsetsController; private @Mock DisplayLayout mMockDisplayLayout; @@ -105,7 +107,7 @@ public class CompatUIControllerTest extends ShellTestCase { doReturn(TASK_ID).when(mMockLetterboxEduLayout).getTaskId(); doReturn(true).when(mMockLetterboxEduLayout).createLayout(anyBoolean()); doReturn(true).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean()); - mController = new CompatUIController(mContext, mMockDisplayController, + mController = new CompatUIController(mContext, mMockShellController, mMockDisplayController, mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor, mMockTransitionsLazy) { @Override @@ -124,6 +126,11 @@ public class CompatUIControllerTest extends ShellTestCase { } @Test + public void instantiateController_registerKeyguardChangeListener() { + verify(mMockShellController, times(1)).addKeyguardChangeListener(any()); + } + + @Test public void testListenerRegistered() { verify(mMockDisplayController).addDisplayWindowListener(mController); verify(mMockImeController).addPositionProcessor(mController); @@ -324,7 +331,7 @@ public class CompatUIControllerTest extends ShellTestCase { /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); // Verify that the restart button is hidden after keyguard becomes showing. - mController.onKeyguardShowingChanged(true); + mController.onKeyguardVisibilityChanged(true, false, false); verify(mMockCompatLayout).updateVisibility(false); verify(mMockLetterboxEduLayout).updateVisibility(false); @@ -340,7 +347,7 @@ public class CompatUIControllerTest extends ShellTestCase { false); // Verify button is shown after keyguard becomes not showing. - mController.onKeyguardShowingChanged(false); + mController.onKeyguardVisibilityChanged(false, false, false); verify(mMockCompatLayout).updateVisibility(true); verify(mMockLetterboxEduLayout).updateVisibility(true); @@ -352,7 +359,7 @@ public class CompatUIControllerTest extends ShellTestCase { /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); - mController.onKeyguardShowingChanged(true); + mController.onKeyguardVisibilityChanged(true, false, false); verify(mMockCompatLayout, times(2)).updateVisibility(false); verify(mMockLetterboxEduLayout, times(2)).updateVisibility(false); @@ -360,7 +367,7 @@ public class CompatUIControllerTest extends ShellTestCase { clearInvocations(mMockCompatLayout, mMockLetterboxEduLayout); // Verify button remains hidden after keyguard becomes not showing since IME is showing. - mController.onKeyguardShowingChanged(false); + mController.onKeyguardVisibilityChanged(false, false, false); verify(mMockCompatLayout).updateVisibility(false); verify(mMockLetterboxEduLayout).updateVisibility(false); @@ -378,7 +385,7 @@ public class CompatUIControllerTest extends ShellTestCase { /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); - mController.onKeyguardShowingChanged(true); + mController.onKeyguardVisibilityChanged(true, false, false); verify(mMockCompatLayout, times(2)).updateVisibility(false); verify(mMockLetterboxEduLayout, times(2)).updateVisibility(false); @@ -392,7 +399,7 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLetterboxEduLayout).updateVisibility(false); // Verify button is shown after keyguard becomes not showing. - mController.onKeyguardShowingChanged(false); + mController.onKeyguardVisibilityChanged(false, false, false); verify(mMockCompatLayout).updateVisibility(true); verify(mMockLetterboxEduLayout).updateVisibility(true); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java index 0b43163787f3..e209971998c8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java @@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DragEvent.ACTION_DRAG_STARTED; import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -48,6 +49,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.sysui.ShellController; import org.junit.Before; import org.junit.Test; @@ -66,24 +68,34 @@ public class DragAndDropControllerTest extends ShellTestCase { @Mock private Context mContext; - + @Mock + private ShellController mShellController; @Mock private DisplayController mDisplayController; - @Mock private UiEventLogger mUiEventLogger; - @Mock private DragAndDropController.DragAndDropListener mDragAndDropListener; + @Mock + private IconProvider mIconProvider; + @Mock + private ShellExecutor mMainExecutor; + @Mock + private SplitScreenController mSplitScreenController; private DragAndDropController mController; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger, - mock(IconProvider.class), mock(ShellExecutor.class)); - mController.initialize(Optional.of(mock(SplitScreenController.class))); + mController = new DragAndDropController(mContext, mShellController, mDisplayController, + mUiEventLogger, mIconProvider, mMainExecutor); + mController.initialize(Optional.of(mSplitScreenController)); + } + + @Test + public void instantiateController_registerConfigChangeListener() { + verify(mShellController, times(1)).addConfigurationChangeListener(any()); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutControllerTest.java index 7ecd5020d56e..dcc504ad0cdb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutControllerTest.java @@ -16,7 +16,9 @@ package com.android.wm.shell.hidedisplaycutout; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.testing.AndroidTestingRunner; @@ -27,7 +29,7 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.sysui.ShellController; import org.junit.Before; import org.junit.Test; @@ -42,17 +44,23 @@ public class HideDisplayCutoutControllerTest extends ShellTestCase { private TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getTargetContext(), null); - private HideDisplayCutoutController mHideDisplayCutoutController; @Mock - private HideDisplayCutoutOrganizer mMockDisplayAreaOrganizer; + private ShellController mShellController; @Mock - private ShellExecutor mMockMainExecutor; + private HideDisplayCutoutOrganizer mMockDisplayAreaOrganizer; + + private HideDisplayCutoutController mHideDisplayCutoutController; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mHideDisplayCutoutController = new HideDisplayCutoutController( - mContext, mMockDisplayAreaOrganizer, mMockMainExecutor); + mContext, mShellController, mMockDisplayAreaOrganizer); + } + + @Test + public void instantiateController_registerConfigChangeListener() { + verify(mShellController, times(1)).addConfigurationChangeListener(any()); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index 8a2bbd75db57..dbf93ae35c18 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,6 +49,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; +import com.android.wm.shell.sysui.ShellController; import org.junit.Before; import org.junit.Test; @@ -68,6 +70,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { OneHandedState mSpiedTransitionState; @Mock + ShellController mMockShellController; + @Mock DisplayLayout mDisplayLayout; @Mock DisplayController mMockDisplayController; @@ -123,6 +127,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { mOneHandedAccessibilityUtil = new OneHandedAccessibilityUtil(mContext); mSpiedOneHandedController = spy(new OneHandedController( mContext, + mMockShellController, mMockDisplayController, mMockDisplayAreaOrganizer, mMockTouchHandler, @@ -139,6 +144,16 @@ public class OneHandedControllerTest extends OneHandedTestCase { } @Test + public void testControllerRegistersConfigChangeListener() { + verify(mMockShellController, times(1)).addConfigurationChangeListener(any()); + } + + @Test + public void testControllerRegistersKeyguardChangeListener() { + verify(mMockShellController, times(1)).addKeyguardChangeListener(any()); + } + + @Test public void testDefaultShouldNotInOneHanded() { // Assert default transition state is STATE_NONE assertThat(mSpiedTransitionState.getState()).isEqualTo(STATE_NONE); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java index 7ee7536d454d..e6a8220e081b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.when; import android.graphics.Rect; import android.os.Handler; -import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.util.ArrayMap; import android.view.Display; @@ -42,6 +41,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; +import com.android.wm.shell.sysui.ShellController; import org.junit.Before; import org.junit.Test; @@ -52,7 +52,6 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) public class OneHandedStateTest extends OneHandedTestCase { - private int mCurrentUser = UserHandle.myUserId(); Display mDisplay; DisplayLayout mDisplayLayout; @@ -62,6 +61,8 @@ public class OneHandedStateTest extends OneHandedTestCase { OneHandedState mSpiedState; @Mock + ShellController mMockShellController; + @Mock DisplayController mMockDisplayController; @Mock OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; @@ -110,6 +111,7 @@ public class OneHandedStateTest extends OneHandedTestCase { mOneHandedAccessibilityUtil = new OneHandedAccessibilityUtil(mContext); mSpiedOneHandedController = spy(new OneHandedController( mContext, + mMockShellController, mMockDisplayController, mMockDisplayAreaOrganizer, mMockTouchHandler, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java index 52d78ca7a004..5880ffb0dce2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java @@ -37,6 +37,7 @@ import android.testing.TestableLooper; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; import com.android.wm.shell.MockSurfaceControlHelper; import com.android.wm.shell.ShellTestCase; @@ -62,19 +63,18 @@ public class PipAnimationControllerTest extends ShellTestCase { @Mock private TaskInfo mTaskInfo; - @Mock private PipAnimationController.PipAnimationCallback mPipAnimationCallback; @Before public void setUp() throws Exception { - mPipAnimationController = new PipAnimationController( - new PipSurfaceTransactionHelper()); + MockitoAnnotations.initMocks(this); + mPipAnimationController = new PipAnimationController(new PipSurfaceTransactionHelper( + InstrumentationRegistry.getInstrumentation().getTargetContext())); mLeash = new SurfaceControl.Builder() .setContainerLayer() .setName("FakeLeash") .build(); - MockitoAnnotations.initMocks(this); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index b351f8fcf838..857f578fd8ed 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -42,6 +42,7 @@ import android.testing.TestableLooper; import android.util.Rational; import android.util.Size; import android.view.DisplayInfo; +import android.view.SurfaceControl; import android.window.WindowContainerToken; import com.android.wm.shell.MockSurfaceControlHelper; @@ -150,7 +151,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { final Rational aspectRatio = new Rational(2, 1); mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(aspectRatio)), null /* leash */); + createPipParams(aspectRatio)), mock(SurfaceControl.class)); assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f); } @@ -158,7 +159,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskAppeared_updatesLastPipComponentName() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), - null /* leash */); + mock(SurfaceControl.class)); assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName()); } @@ -169,7 +170,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { mSpiedPipTaskOrganizer.onTaskAppeared( createTaskInfo(mComponent1, createPipParams(null), minSize), - null /* leash */); + mock(SurfaceControl.class)); assertEquals(minSize, mPipBoundsState.getOverrideMinSize()); } @@ -179,7 +180,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { final Rational startAspectRatio = new Rational(2, 1); final Rational newAspectRatio = new Rational(1, 2); mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(startAspectRatio)), null /* leash */); + createPipParams(startAspectRatio)), mock(SurfaceControl.class)); // It is in entering transition, should defer onTaskInfoChanged callback in this case. mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, @@ -197,7 +198,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { final Rational startAspectRatio = new Rational(2, 1); final Rational newAspectRatio = new Rational(1, 2); mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(startAspectRatio)), null /* leash */); + createPipParams(startAspectRatio)), mock(SurfaceControl.class)); mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, @@ -210,7 +211,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskInfoChanged_inPip_updatesLastPipComponentName() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(null)), null /* leash */); + createPipParams(null)), mock(SurfaceControl.class)); mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, @@ -222,7 +223,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskInfoChanged_inPip_updatesOverrideMinSize() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(null)), null /* leash */); + createPipParams(null)), mock(SurfaceControl.class)); mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); final Size minSize = new Size(400, 320); @@ -235,7 +236,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Test public void onTaskVanished_clearsPipBounds() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, - createPipParams(null)), null /* leash */); + createPipParams(null)), mock(SurfaceControl.class)); mPipBoundsState.setBounds(new Rect(100, 100, 200, 150)); mSpiedPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null))); 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 babc9707ef9c..f192514c37ab 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 @@ -24,6 +24,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -54,6 +55,7 @@ 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.sysui.ShellController; import org.junit.Before; import org.junit.Test; @@ -73,6 +75,7 @@ import java.util.Set; public class PipControllerTest extends ShellTestCase { private PipController mPipController; + @Mock private ShellController mMockShellController; @Mock private DisplayController mMockDisplayController; @Mock private PhonePipMenuController mMockPhonePipMenuController; @Mock private PipAppOpsListener mMockPipAppOpsListener; @@ -102,7 +105,7 @@ public class PipControllerTest extends ShellTestCase { ((Runnable) invocation.getArgument(0)).run(); return null; }).when(mMockExecutor).execute(any()); - mPipController = new PipController(mContext, mMockDisplayController, + mPipController = new PipController(mContext, mMockShellController, mMockDisplayController, mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm, mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, @@ -115,6 +118,16 @@ public class PipControllerTest extends ShellTestCase { } @Test + public void instantiatePipController_registerConfigChangeListener() { + verify(mMockShellController, times(1)).addConfigurationChangeListener(any()); + } + + @Test + public void instantiatePipController_registerKeyguardChangeListener() { + verify(mMockShellController, times(1)).addKeyguardChangeListener(any()); + } + + @Test public void instantiatePipController_registersPipTransitionCallback() { verify(mMockPipTransitionController).registerPipTransitionCallback(any()); } @@ -136,7 +149,7 @@ public class PipControllerTest extends ShellTestCase { when(mockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); when(spyContext.getPackageManager()).thenReturn(mockPackageManager); - assertNull(PipController.create(spyContext, mMockDisplayController, + assertNull(PipController.create(spyContext, mMockShellController, mMockDisplayController, mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm, mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java index c10e4a143076..c7a261f32e43 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java @@ -28,6 +28,9 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.ComponentName; @@ -44,10 +47,12 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; +import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -65,6 +70,7 @@ import java.util.Optional; @RunWith(AndroidJUnit4.class) public class SplitScreenControllerTests extends ShellTestCase { + @Mock ShellController mShellController; @Mock ShellTaskOrganizer mTaskOrganizer; @Mock SyncTransactionQueue mSyncQueue; @Mock RootTaskDisplayAreaOrganizer mRootTDAOrganizer; @@ -82,10 +88,17 @@ public class SplitScreenControllerTests extends ShellTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - mSplitScreenController = spy(new SplitScreenController(mTaskOrganizer, mSyncQueue, mContext, - mRootTDAOrganizer, mMainExecutor, mDisplayController, mDisplayImeController, - mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider, - mRecentTasks)); + mSplitScreenController = spy(new SplitScreenController(mShellController, mTaskOrganizer, + mSyncQueue, mContext, mRootTDAOrganizer, mMainExecutor, mDisplayController, + mDisplayImeController, mDisplayInsetsController, mTransitions, mTransactionPool, + mIconProvider, mRecentTasks)); + } + + @Test + public void testControllerRegistersKeyguardChangeListener() { + when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout()); + mSplitScreenController.onOrganizerRegistered(); + verify(mShellController, times(1)).addKeyguardChangeListener(any()); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 304ca66dd3bb..1d038f4ee377 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -182,7 +182,7 @@ public class SplitTransitionTests extends ShellTestCase { IBinder transition = mSplitScreenTransitions.startEnterTransition( TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), - new RemoteTransition(testRemote), mStageCoordinator); + new RemoteTransition(testRemote), mStageCoordinator, null); mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface()); boolean accepted = mStageCoordinator.startAnimation(transition, info, @@ -422,7 +422,7 @@ public class SplitTransitionTests extends ShellTestCase { TransitionInfo enterInfo = createEnterPairInfo(); IBinder enterTransit = mSplitScreenTransitions.startEnterTransition( TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), - new RemoteTransition(new TestRemoteTransition()), mStageCoordinator); + new RemoteTransition(new TestRemoteTransition()), mStageCoordinator, null); mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface()); mStageCoordinator.startAnimation(enterTransit, enterInfo, 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 46b040fd4325..e5ae2962e6e4 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 @@ -251,7 +251,7 @@ public class StartingSurfaceDrawerTests extends ShellTestCase { anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* requestedVisibility */, any() /* outInputChannel */, any() /* outInsetsState */, any() /* outActiveControls */, - any() /* outAttachedFrame */); + any() /* outAttachedFrame */, any() /* outSizeCompatScale */); TaskSnapshotWindow mockSnapshotWindow = TaskSnapshotWindow.create(windowInfo, mBinder, snapshot, mTestExecutor, () -> { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java new file mode 100644 index 000000000000..1c0e46f7264e --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sysui/ShellControllerTest.java @@ -0,0 +1,331 @@ +/* + * 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.wm.shell.sysui; + +import static org.junit.Assert.assertTrue; + +import android.content.res.Configuration; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.common.ShellExecutor; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Locale; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class ShellControllerTest extends ShellTestCase { + + @Mock + private ShellExecutor mExecutor; + + private ShellController mController; + private TestConfigurationChangeListener mConfigChangeListener; + private TestKeyguardChangeListener mKeyguardChangeListener; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mKeyguardChangeListener = new TestKeyguardChangeListener(); + mConfigChangeListener = new TestConfigurationChangeListener(); + mController = new ShellController(mExecutor); + mController.onConfigurationChanged(getConfigurationCopy()); + } + + @After + public void tearDown() { + // Do nothing + } + + @Test + public void testAddKeyguardChangeListener_ensureCallback() { + mController.addKeyguardChangeListener(mKeyguardChangeListener); + + mController.onKeyguardVisibilityChanged(true, false, false); + assertTrue(mKeyguardChangeListener.visibilityChanged == 1); + assertTrue(mKeyguardChangeListener.dismissAnimationFinished == 0); + } + + @Test + public void testDoubleAddKeyguardChangeListener_ensureSingleCallback() { + mController.addKeyguardChangeListener(mKeyguardChangeListener); + mController.addKeyguardChangeListener(mKeyguardChangeListener); + + mController.onKeyguardVisibilityChanged(true, false, false); + assertTrue(mKeyguardChangeListener.visibilityChanged == 1); + assertTrue(mKeyguardChangeListener.dismissAnimationFinished == 0); + } + + @Test + public void testAddRemoveKeyguardChangeListener_ensureNoCallback() { + mController.addKeyguardChangeListener(mKeyguardChangeListener); + mController.removeKeyguardChangeListener(mKeyguardChangeListener); + + mController.onKeyguardVisibilityChanged(true, false, false); + assertTrue(mKeyguardChangeListener.visibilityChanged == 0); + assertTrue(mKeyguardChangeListener.dismissAnimationFinished == 0); + } + + @Test + public void testKeyguardVisibilityChanged() { + mController.addKeyguardChangeListener(mKeyguardChangeListener); + + mController.onKeyguardVisibilityChanged(true, true, true); + assertTrue(mKeyguardChangeListener.visibilityChanged == 1); + assertTrue(mKeyguardChangeListener.lastAnimatingDismiss); + assertTrue(mKeyguardChangeListener.lastOccluded); + assertTrue(mKeyguardChangeListener.lastAnimatingDismiss); + assertTrue(mKeyguardChangeListener.dismissAnimationFinished == 0); + } + + @Test + public void testKeyguardDismissAnimationFinished() { + mController.addKeyguardChangeListener(mKeyguardChangeListener); + + mController.onKeyguardDismissAnimationFinished(); + assertTrue(mKeyguardChangeListener.visibilityChanged == 0); + assertTrue(mKeyguardChangeListener.dismissAnimationFinished == 1); + } + + @Test + public void testAddConfigurationChangeListener_ensureCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + } + + @Test + public void testDoubleAddConfigurationChangeListener_ensureSingleCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + } + + @Test + public void testAddRemoveConfigurationChangeListener_ensureNoCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + mController.removeConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 0); + } + + @Test + public void testMultipleConfigurationChangeListeners() { + TestConfigurationChangeListener listener2 = new TestConfigurationChangeListener(); + mController.addConfigurationChangeListener(mConfigChangeListener); + mController.addConfigurationChangeListener(listener2); + + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(listener2.configChanges == 1); + } + + @Test + public void testRemoveListenerDuringCallback() { + TestConfigurationChangeListener badListener = new TestConfigurationChangeListener() { + @Override + public void onConfigurationChanged(Configuration newConfiguration) { + mController.removeConfigurationChangeListener(this); + } + }; + mController.addConfigurationChangeListener(badListener); + mController.addConfigurationChangeListener(mConfigChangeListener); + + // Ensure we don't fail just because a listener was removed mid-callback + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + } + + @Test + public void testDensityChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.densityDpi = 200; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 1); + assertTrue(mConfigChangeListener.smallestWidthChanges == 0); + assertTrue(mConfigChangeListener.themeChanges == 0); + assertTrue(mConfigChangeListener.localeChanges == 0); + } + + @Test + public void testFontScaleChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.fontScale = 2; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 1); + assertTrue(mConfigChangeListener.smallestWidthChanges == 0); + assertTrue(mConfigChangeListener.themeChanges == 0); + assertTrue(mConfigChangeListener.localeChanges == 0); + } + + @Test + public void testSmallestWidthChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.smallestScreenWidthDp = 100; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 0); + assertTrue(mConfigChangeListener.smallestWidthChanges == 1); + assertTrue(mConfigChangeListener.themeChanges == 0); + assertTrue(mConfigChangeListener.localeChanges == 0); + } + + @Test + public void testThemeChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.assetsSeq++; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 0); + assertTrue(mConfigChangeListener.smallestWidthChanges == 0); + assertTrue(mConfigChangeListener.themeChanges == 1); + assertTrue(mConfigChangeListener.localeChanges == 0); + } + + @Test + public void testNightModeChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + newConfig.uiMode = Configuration.UI_MODE_NIGHT_YES; + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 0); + assertTrue(mConfigChangeListener.smallestWidthChanges == 0); + assertTrue(mConfigChangeListener.themeChanges == 1); + assertTrue(mConfigChangeListener.localeChanges == 0); + } + + @Test + public void testLocaleChangeCallback() { + mController.addConfigurationChangeListener(mConfigChangeListener); + + Configuration newConfig = getConfigurationCopy(); + // Just change the locales to be different + if (newConfig.locale == Locale.CANADA) { + newConfig.locale = Locale.US; + } else { + newConfig.locale = Locale.CANADA; + } + mController.onConfigurationChanged(newConfig); + assertTrue(mConfigChangeListener.configChanges == 1); + assertTrue(mConfigChangeListener.densityChanges == 0); + assertTrue(mConfigChangeListener.smallestWidthChanges == 0); + assertTrue(mConfigChangeListener.themeChanges == 0); + assertTrue(mConfigChangeListener.localeChanges == 1); + } + + private Configuration getConfigurationCopy() { + final Configuration c = new Configuration(InstrumentationRegistry.getInstrumentation() + .getTargetContext().getResources().getConfiguration()); + // In tests this might be undefined so make sure it's valid + c.assetsSeq = 1; + return c; + } + + private class TestConfigurationChangeListener implements ConfigurationChangeListener { + // Counts of number of times each of the callbacks are called + public int configChanges; + public int densityChanges; + public int smallestWidthChanges; + public int themeChanges; + public int localeChanges; + + @Override + public void onConfigurationChanged(Configuration newConfiguration) { + configChanges++; + } + + @Override + public void onDensityOrFontScaleChanged() { + densityChanges++; + } + + @Override + public void onSmallestScreenWidthChanged() { + smallestWidthChanges++; + } + + @Override + public void onThemeChanged() { + themeChanges++; + } + + @Override + public void onLocaleOrLayoutDirectionChanged() { + localeChanges++; + } + } + + private class TestKeyguardChangeListener implements KeyguardChangeListener { + // Counts of number of times each of the callbacks are called + public int visibilityChanged; + public boolean lastVisibility; + public boolean lastOccluded; + public boolean lastAnimatingDismiss; + public int dismissAnimationFinished; + + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + lastVisibility = visible; + lastOccluded = occluded; + lastAnimatingDismiss = animatingDismiss; + visibilityChanged++; + } + + @Override + public void onKeyguardDismissAnimationFinished() { + dismissAnimationFinished++; + } + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java deleted file mode 100644 index 7583418fc018..000000000000 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/tasksurfacehelper/TaskSurfaceHelperControllerTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2021 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.wm.shell.tasksurfacehelper; - -import static org.mockito.Mockito.verify; - -import android.testing.AndroidTestingRunner; -import android.view.SurfaceControl; - -import androidx.test.filters.SmallTest; - -import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.ShellExecutor; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidTestingRunner.class) -@SmallTest -public class TaskSurfaceHelperControllerTest extends ShellTestCase { - private TaskSurfaceHelperController mTaskSurfaceHelperController; - @Mock - private ShellTaskOrganizer mMockTaskOrganizer; - @Mock - private ShellExecutor mMockShellExecutor; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mTaskSurfaceHelperController = new TaskSurfaceHelperController( - mMockTaskOrganizer, mMockShellExecutor); - } - - @Test - public void testSetGameModeForTask() { - mTaskSurfaceHelperController.setGameModeForTask(/*taskId*/1, /*gameMode*/3); - verify(mMockTaskOrganizer).setSurfaceMetadata(1, SurfaceControl.METADATA_GAME_MODE, 3); - } -} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index 680034bd2ea5..b318bb26a51d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -21,23 +21,32 @@ import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceCon import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.content.Context; import android.graphics.Color; +import android.graphics.Point; import android.graphics.Rect; import android.testing.AndroidTestingRunner; +import android.util.DisplayMetrics; import android.view.Display; +import android.view.InsetsState; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; import android.view.View; +import android.view.ViewRootImpl; +import android.view.WindowManager.LayoutParams; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; @@ -53,6 +62,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import java.util.ArrayList; +import java.util.List; import java.util.function.Supplier; /** @@ -66,6 +77,8 @@ import java.util.function.Supplier; public class WindowDecorationTests extends ShellTestCase { private static final int CAPTION_HEIGHT_DP = 32; private static final int SHADOW_RADIUS_DP = 5; + private static final Rect TASK_BOUNDS = new Rect(100, 300, 400, 400); + private static final Point TASK_POSITION_IN_PARENT = new Point(40, 60); private final Rect mOutsetsDp = new Rect(); private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult = @@ -84,19 +97,142 @@ public class WindowDecorationTests extends ShellTestCase { @Mock private WindowContainerTransaction mMockWindowContainerTransaction; - private SurfaceControl.Builder mMockSurfaceControlBuilder; - private SurfaceControl.Transaction mMockSurfaceControlTransaction; + private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>(); + private SurfaceControl.Transaction mMockSurfaceControlStartT; + private SurfaceControl.Transaction mMockSurfaceControlFinishT; @Before public void setUp() { - mMockSurfaceControlBuilder = createMockSurfaceControlBuilder(mock(SurfaceControl.class)); - mMockSurfaceControlTransaction = createMockSurfaceControlTransaction(); + mMockSurfaceControlStartT = createMockSurfaceControlTransaction(); + mMockSurfaceControlFinishT = createMockSurfaceControlTransaction(); doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory) .create(any(), any(), any(), anyBoolean()); } @Test + public void testLayoutResultCalculation_invisibleTask() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final SurfaceControl decorContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder decorContainerSurfaceBuilder = + createMockSurfaceControlBuilder(decorContainerSurface); + mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder); + final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder taskBackgroundSurfaceBuilder = + createMockSurfaceControlBuilder(taskBackgroundSurface); + mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder); + + final ActivityManager.TaskDescription.Builder taskDescriptionBuilder = + new ActivityManager.TaskDescription.Builder() + .setBackgroundColor(Color.YELLOW); + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setTaskDescriptionBuilder(taskDescriptionBuilder) + .setBounds(TASK_BOUNDS) + .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y) + .setVisible(false) + .build(); + taskInfo.isFocused = false; + // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is + // 64px. + taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; + mOutsetsDp.set(10, 20, 30, 40); + + final SurfaceControl taskSurface = mock(SurfaceControl.class); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); + + windowDecor.relayout(taskInfo); + + verify(decorContainerSurfaceBuilder, never()).build(); + verify(taskBackgroundSurfaceBuilder, never()).build(); + verify(mMockSurfaceControlViewHostFactory, never()) + .create(any(), any(), any(), anyBoolean()); + + verify(mMockSurfaceControlFinishT).hide(taskSurface); + + assertNull(mRelayoutResult.mRootView); + } + + @Test + public void testLayoutResultCalculation_visibleFocusedTask() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final SurfaceControl decorContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder decorContainerSurfaceBuilder = + createMockSurfaceControlBuilder(decorContainerSurface); + mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder); + final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder taskBackgroundSurfaceBuilder = + createMockSurfaceControlBuilder(taskBackgroundSurface); + mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder); + + final ActivityManager.TaskDescription.Builder taskDescriptionBuilder = + new ActivityManager.TaskDescription.Builder() + .setBackgroundColor(Color.YELLOW); + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setTaskDescriptionBuilder(taskDescriptionBuilder) + .setBounds(TASK_BOUNDS) + .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y) + .setVisible(true) + .build(); + taskInfo.isFocused = true; + // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is + // 64px. + taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; + mOutsetsDp.set(10, 20, 30, 40); + + final SurfaceControl taskSurface = mock(SurfaceControl.class); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); + + windowDecor.relayout(taskInfo); + + verify(decorContainerSurfaceBuilder).setParent(taskSurface); + verify(decorContainerSurfaceBuilder).setContainerLayer(); + verify(mMockSurfaceControlStartT).setTrustedOverlay(decorContainerSurface, true); + verify(mMockSurfaceControlStartT).setPosition(decorContainerSurface, -20, -40); + verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 380, 220); + + verify(taskBackgroundSurfaceBuilder).setParent(taskSurface); + verify(taskBackgroundSurfaceBuilder).setEffectLayer(); + verify(mMockSurfaceControlStartT).setWindowCrop(taskBackgroundSurface, 300, 100); + verify(mMockSurfaceControlStartT) + .setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f}); + verify(mMockSurfaceControlStartT).setShadowRadius(taskBackgroundSurface, 10); + + verify(mMockSurfaceControlViewHostFactory) + .create(any(), eq(defaultDisplay), any(), anyBoolean()); + verify(mMockSurfaceControlViewHost) + .setView(same(mMockView), + argThat(lp -> lp.height == 64 + && lp.width == 300 + && (lp.flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0)); + if (ViewRootImpl.CAPTION_ON_SHELL) { + verify(mMockView).setTaskFocusState(true); + verify(mMockWindowContainerTransaction) + .addRectInsetsProvider(taskInfo.token, + new Rect(100, 300, 400, 364), + new int[] { InsetsState.ITYPE_CAPTION_BAR }); + } + + verify(mMockSurfaceControlFinishT) + .setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y); + verify(mMockSurfaceControlFinishT) + .setCrop(taskSurface, new Rect(-20, -40, 360, 180)); + verify(mMockSurfaceControlStartT) + .show(taskSurface); + + assertEquals(380, mRelayoutResult.mWidth); + assertEquals(220, mRelayoutResult.mHeight); + assertEquals(2, mRelayoutResult.mDensity, 0.f); + } + + @Test public void testNotCrashWhenDisplayAppearsAfterTask() { doReturn(mock(Display.class)).when(mMockDisplayController) .getDisplay(Display.DEFAULT_DISPLAY); @@ -145,10 +281,24 @@ public class WindowDecorationTests extends ShellTestCase { private TestWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) { return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer, - taskInfo, testSurface, () -> mMockSurfaceControlBuilder, + taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(), mMockSurfaceControlViewHostFactory); } + private class MockSurfaceControlBuilderSupplier implements Supplier<SurfaceControl.Builder> { + private int mNumOfCalls = 0; + + @Override + public SurfaceControl.Builder get() { + final SurfaceControl.Builder builder = + mNumOfCalls < mMockSurfaceControlBuilders.size() + ? mMockSurfaceControlBuilders.get(mNumOfCalls) + : createMockSurfaceControlBuilder(mock(SurfaceControl.class)); + ++mNumOfCalls; + return builder; + } + } + private static class TestView extends View implements TaskFocusStateConsumer { private TestView(Context context) { super(context); @@ -171,8 +321,8 @@ public class WindowDecorationTests extends ShellTestCase { @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { relayout(null /* taskInfo */, 0 /* layoutResId */, mMockView, CAPTION_HEIGHT_DP, - mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlTransaction, - mMockWindowContainerTransaction, mRelayoutResult); + mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlStartT, + mMockSurfaceControlFinishT, mMockWindowContainerTransaction, mRelayoutResult); } } } diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp index d86d9ee56f4c..19efc5f09d11 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -20,18 +20,21 @@ #include <minikin/FontCollection.h> #include <minikin/FontFamily.h> #include <minikin/FontFileParser.h> +#include <minikin/LocaleList.h> +#include <minikin/MinikinFontFactory.h> #include <minikin/SystemFonts.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> + +#include <mutex> +#include <unordered_map> + #include "FontUtils.h" #include "GraphicsJNI.h" #include "SkData.h" #include "SkTypeface.h" #include "fonts/Font.h" -#include <mutex> -#include <unordered_map> - #ifdef __ANDROID__ #include <sys/stat.h> #endif @@ -109,15 +112,15 @@ static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArr std::vector<std::shared_ptr<minikin::FontFamily>> familyVec; Typeface* typeface = (fallbackPtr == 0) ? nullptr : toTypeface(fallbackPtr); if (typeface != nullptr) { - const std::vector<std::shared_ptr<minikin::FontFamily>>& fallbackFamilies = - toTypeface(fallbackPtr)->fFontCollection->getFamilies(); - familyVec.reserve(families.size() + fallbackFamilies.size()); + const std::shared_ptr<minikin::FontCollection>& fallbackCollection = + toTypeface(fallbackPtr)->fFontCollection; + familyVec.reserve(families.size() + fallbackCollection->getFamilyCount()); for (size_t i = 0; i < families.size(); i++) { FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]); familyVec.emplace_back(family->family); } - for (size_t i = 0; i < fallbackFamilies.size(); i++) { - familyVec.emplace_back(fallbackFamilies[i]); + for (size_t i = 0; i < fallbackCollection->getFamilyCount(); i++) { + familyVec.emplace_back(fallbackCollection->getFamilyAt(i)); } } else { familyVec.reserve(families.size()); @@ -204,9 +207,18 @@ static sk_sp<SkData> makeSkDataCached(const std::string& path, bool hasVerity) { return entry; } -static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader); +class MinikinFontSkiaFactory : minikin::MinikinFontFactory { +private: + MinikinFontSkiaFactory() : MinikinFontFactory() { MinikinFontFactory::setInstance(this); } + +public: + static void init() { static MinikinFontSkiaFactory factory; } + void skip(minikin::BufferReader* reader) const override; + std::shared_ptr<minikin::MinikinFont> create(minikin::BufferReader reader) const override; + void write(minikin::BufferWriter* writer, const minikin::MinikinFont* typeface) const override; +}; -static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader) { +void MinikinFontSkiaFactory::skip(minikin::BufferReader* reader) const { // Advance reader's position. reader->skipString(); // fontPath reader->skip<int>(); // fontIndex @@ -216,10 +228,10 @@ static minikin::Font::TypefaceLoader* readMinikinFontSkia(minikin::BufferReader* reader->skip<uint32_t>(); // expectedFontRevision reader->skipString(); // expectedPostScriptName } - return &loadMinikinFontSkia; } -static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::BufferReader reader) { +std::shared_ptr<minikin::MinikinFont> MinikinFontSkiaFactory::create( + minikin::BufferReader reader) const { std::string_view fontPath = reader.readString(); std::string path(fontPath.data(), fontPath.size()); ATRACE_FORMAT("Loading font %s", path.c_str()); @@ -268,8 +280,8 @@ static std::shared_ptr<minikin::MinikinFont> loadMinikinFontSkia(minikin::Buffer return minikinFont; } -static void writeMinikinFontSkia(minikin::BufferWriter* writer, - const minikin::MinikinFont* typeface) { +void MinikinFontSkiaFactory::write(minikin::BufferWriter* writer, + const minikin::MinikinFont* typeface) const { // When you change the format of font metadata, please update code to parse // typefaceMetadataReader() in // frameworks/base/libs/hwui/jni/fonts/Font.cpp too. @@ -294,6 +306,7 @@ static void writeMinikinFontSkia(minikin::BufferWriter* writer, } static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongArray faceHandles) { + MinikinFontSkiaFactory::init(); ScopedLongArrayRO faces(env, faceHandles); std::vector<Typeface*> typefaces; typefaces.reserve(faces.size()); @@ -310,7 +323,7 @@ static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongA fontCollections.push_back(typeface->fFontCollection); } } - minikin::FontCollection::writeVector<writeMinikinFontSkia>(&writer, fontCollections); + minikin::FontCollection::writeVector(&writer, fontCollections); writer.write<uint32_t>(typefaces.size()); for (Typeface* typeface : typefaces) { writer.write<uint32_t>(fcToIndex.find(typeface->fFontCollection)->second); @@ -322,11 +335,12 @@ static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongA } static jlongArray Typeface_readTypefaces(JNIEnv *env, jobject, jobject buffer) { + MinikinFontSkiaFactory::init(); void* addr = buffer == nullptr ? nullptr : env->GetDirectBufferAddress(buffer); if (addr == nullptr) return nullptr; minikin::BufferReader reader(addr); std::vector<std::shared_ptr<minikin::FontCollection>> fontCollections = - minikin::FontCollection::readVector<readMinikinFontSkia>(&reader); + minikin::FontCollection::readVector(&reader); uint32_t typefaceCount = reader.read<uint32_t>(); std::vector<jlong> faceHandles; faceHandles.reserve(typefaceCount); @@ -358,13 +372,13 @@ static void Typeface_forceSetStaticFinalField(JNIEnv *env, jclass cls, jstring f // Critical Native static jint Typeface_getFamilySize(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) { - return toTypeface(faceHandle)->fFontCollection->getFamilies().size(); + return toTypeface(faceHandle)->fFontCollection->getFamilyCount(); } // Critical Native static jlong Typeface_getFamily(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle, jint index) { std::shared_ptr<minikin::FontFamily> family = - toTypeface(faceHandle)->fFontCollection->getFamilies()[index]; + toTypeface(faceHandle)->fFontCollection->getFamilyAt(index); return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family))); } @@ -380,6 +394,12 @@ static void Typeface_addFontCollection(CRITICAL_JNI_PARAMS_COMMA jlong faceHandl minikin::SystemFonts::addFontMap(std::move(collection)); } +// Fast Native +static void Typeface_registerLocaleList(JNIEnv* env, jobject, jstring jLocales) { + ScopedUtfChars locales(env, jLocales); + minikin::registerLocaleList(locales.c_str()); +} + /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gTypefaceMethods[] = { @@ -405,6 +425,7 @@ static const JNINativeMethod gTypefaceMethods[] = { {"nativeGetFamily", "(JI)J", (void*)Typeface_getFamily}, {"nativeWarmUpCache", "(Ljava/lang/String;)V", (void*)Typeface_warmUpCache}, {"nativeAddFontCollections", "(J)V", (void*)Typeface_addFontCollection}, + {"nativeRegisterLocaleList", "(Ljava/lang/String;)V", (void*)Typeface_registerLocaleList}, }; int register_android_graphics_Typeface(JNIEnv* env) diff --git a/libs/hwui/thread/WorkQueue.h b/libs/hwui/thread/WorkQueue.h index 46b8bc07b432..f2751d2a6cc7 100644 --- a/libs/hwui/thread/WorkQueue.h +++ b/libs/hwui/thread/WorkQueue.h @@ -57,7 +57,7 @@ private: public: WorkQueue(std::function<void()>&& wakeFunc, std::mutex& lock) - : mWakeFunc(move(wakeFunc)), mLock(lock) {} + : mWakeFunc(std::move(wakeFunc)), mLock(lock) {} void process() { auto now = clock::now(); diff --git a/libs/incident/libincident.map.txt b/libs/incident/libincident.map.txt index f157763f1a03..f75cceaf59fa 100644 --- a/libs/incident/libincident.map.txt +++ b/libs/incident/libincident.map.txt @@ -1,15 +1,15 @@ LIBINCIDENT { global: - AIncidentReportArgs_init; # apex # introduced=30 - AIncidentReportArgs_clone; # apex # introduced=30 - AIncidentReportArgs_delete; # apex # introduced=30 - AIncidentReportArgs_setAll; # apex # introduced=30 - AIncidentReportArgs_setPrivacyPolicy; # apex # introduced=30 - AIncidentReportArgs_addSection; # apex # introduced=30 - AIncidentReportArgs_setReceiverPackage; # apex # introduced=30 - AIncidentReportArgs_setReceiverClass; # apex # introduced=30 - AIncidentReportArgs_addHeader; # apex # introduced=30 - AIncidentReportArgs_takeReport; # apex # introduced=30 + AIncidentReportArgs_init; # systemapi # introduced=30 + AIncidentReportArgs_clone; # systemapi # introduced=30 + AIncidentReportArgs_delete; # systemapi # introduced=30 + AIncidentReportArgs_setAll; # systemapi # introduced=30 + AIncidentReportArgs_setPrivacyPolicy; # systemapi # introduced=30 + AIncidentReportArgs_addSection; # systemapi # introduced=30 + AIncidentReportArgs_setReceiverPackage; # systemapi # introduced=30 + AIncidentReportArgs_setReceiverClass; # systemapi # introduced=30 + AIncidentReportArgs_addHeader; # systemapi # introduced=30 + AIncidentReportArgs_takeReport; # systemapi # introduced=30 local: *; }; |