diff options
998 files changed, 31815 insertions, 15543 deletions
diff --git a/Android.bp b/Android.bp index 7f4871f5032a..af205d8f0646 100644 --- a/Android.bp +++ b/Android.bp @@ -261,7 +261,6 @@ java_library { "devicepolicyprotosnano", "ImmutabilityAnnotation", - "com.android.sysprop.init", "com.android.sysprop.localization", "PlatformProperties", ], diff --git a/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java index 6363e9c3ef21..25e4c4341b43 100644 --- a/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java +++ b/apct-tests/perftests/core/src/android/libcore/SystemArrayCopyPerfTest.java @@ -16,7 +16,8 @@ package android.libcore; -import android.perftests.utils.BenchmarkState; +import androidx.benchmark.BenchmarkState; +import androidx.benchmark.junit4.BenchmarkRule; import android.perftests.utils.PerfStatusReporter; import androidx.test.filters.LargeTest; @@ -34,7 +35,8 @@ import java.util.Collection; @RunWith(JUnitParamsRunner.class) @LargeTest public class SystemArrayCopyPerfTest { - @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + @Rule + public BenchmarkRule mBenchmarkRule = new BenchmarkRule(); public static Collection<Object[]> getData() { return Arrays.asList( @@ -51,7 +53,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; char[] src = new char[len]; char[] dst = new char[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -63,7 +65,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; byte[] src = new byte[len]; byte[] dst = new byte[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -75,7 +77,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; short[] src = new short[len]; short[] dst = new short[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -87,7 +89,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; int[] src = new int[len]; int[] dst = new int[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -99,7 +101,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; long[] src = new long[len]; long[] dst = new long[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -111,7 +113,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; float[] src = new float[len]; float[] dst = new float[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -123,7 +125,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; double[] src = new double[len]; double[] dst = new double[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } @@ -135,7 +137,7 @@ public class SystemArrayCopyPerfTest { final int len = arrayLength; boolean[] src = new boolean[len]; boolean[] dst = new boolean[len]; - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final BenchmarkState state = mBenchmarkRule.getState(); while (state.keepRunning()) { System.arraycopy(src, 0, dst, 0, len); } diff --git a/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java index fbe67a477f5d..c34936f930f9 100644 --- a/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java @@ -19,6 +19,7 @@ package android.text; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RenderNode; +import android.graphics.Typeface; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; @@ -120,13 +121,34 @@ public class VariableFontPerfTest { public void testSetFontVariationSettings() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); final Paint paint = new Paint(PAINT); - final Random random = new Random(0); while (state.keepRunning()) { state.pauseTiming(); - int weight = random.nextInt(1000); + paint.setTypeface(null); + paint.setFontVariationSettings(null); + Typeface.clearTypefaceCachesForTestingPurpose(); state.resumeTiming(); - paint.setFontVariationSettings("'wght' " + weight); + paint.setFontVariationSettings("'wght' 450"); + } + Typeface.clearTypefaceCachesForTestingPurpose(); + } + + @Test + public void testSetFontVariationSettings_Cached() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final Paint paint = new Paint(PAINT); + Typeface.clearTypefaceCachesForTestingPurpose(); + + while (state.keepRunning()) { + state.pauseTiming(); + paint.setTypeface(null); + paint.setFontVariationSettings(null); + state.resumeTiming(); + + paint.setFontVariationSettings("'wght' 450"); } + + Typeface.clearTypefaceCachesForTestingPurpose(); } + } diff --git a/apex/jobscheduler/service/aconfig/job.aconfig b/apex/jobscheduler/service/aconfig/job.aconfig index e8568651eeaa..613b7842ae3a 100644 --- a/apex/jobscheduler/service/aconfig/job.aconfig +++ b/apex/jobscheduler/service/aconfig/job.aconfig @@ -58,3 +58,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "remove_user_during_user_switch" + namespace: "backstage_power" + description: "Remove started user if user will be stopped due to user switch" + bug: "321598070" +} diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index c2aeadaea65c..c1894f0f795f 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -2629,8 +2629,13 @@ public class DeviceIdleController extends SystemService for (int i=0; i<allowPowerExceptIdle.size(); i++) { String pkg = allowPowerExceptIdle.valueAt(i); try { + // On some devices (eg. HSUM), some apps may + // be not be pre-installed on user 0, but may be + // pre-installed on FULL users. Look for pre-installed system + // apps across all users to make sure they're properly + // allowlisted. ApplicationInfo ai = pm.getApplicationInfo(pkg, - PackageManager.MATCH_SYSTEM_ONLY); + PackageManager.MATCH_ANY_USER | PackageManager.MATCH_SYSTEM_ONLY); int appid = UserHandle.getAppId(ai.uid); mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid); mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true); @@ -2641,8 +2646,13 @@ public class DeviceIdleController extends SystemService for (int i=0; i<allowPower.size(); i++) { String pkg = allowPower.valueAt(i); try { + // On some devices (eg. HSUM), some apps may + // be not be pre-installed on user 0, but may be + // pre-installed on FULL users. Look for pre-installed system + // apps across all users to make sure they're properly + // allowlisted. ApplicationInfo ai = pm.getApplicationInfo(pkg, - PackageManager.MATCH_SYSTEM_ONLY); + PackageManager.MATCH_ANY_USER | PackageManager.MATCH_SYSTEM_ONLY); int appid = UserHandle.getAppId(ai.uid); // These apps are on both the whitelist-except-idle as well // as the full whitelist, so they apply in all cases. diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 5f2b01a7304a..3d25ed5aa2b7 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1669,6 +1669,20 @@ public class JobSchedulerService extends com.android.server.SystemService } @Override + public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { + if (!Flags.removeUserDuringUserSwitch() + || from == null + || !mActivityManagerInternal.isEarlyPackageKillEnabledForUserSwitch( + from.getUserIdentifier(), + to.getUserIdentifier())) { + return; + } + synchronized (mLock) { + mStartedUsers = ArrayUtils.removeInt(mStartedUsers, from.getUserIdentifier()); + } + } + + @Override public void onUserStopping(@NonNull TargetUser user) { synchronized (mLock) { mStartedUsers = ArrayUtils.removeInt(mStartedUsers, user.getUserIdentifier()); diff --git a/core/api/current.txt b/core/api/current.txt index 7f2b00485417..c1366a155aed 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -26,6 +26,7 @@ package android { field public static final String BATTERY_STATS = "android.permission.BATTERY_STATS"; field public static final String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; field public static final String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; + field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String BIND_APP_FUNCTION_SERVICE = "android.permission.BIND_APP_FUNCTION_SERVICE"; field public static final String BIND_AUTOFILL_SERVICE = "android.permission.BIND_AUTOFILL_SERVICE"; field public static final String BIND_CALL_REDIRECTION_SERVICE = "android.permission.BIND_CALL_REDIRECTION_SERVICE"; field public static final String BIND_CARRIER_MESSAGING_CLIENT_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE"; @@ -8718,6 +8719,30 @@ package android.app.admin { } +package android.app.appfunctions { + + @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager { + } + + @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class ExecuteAppFunctionRequest implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.os.Bundle getExtras(); + method @NonNull public String getFunctionIdentifier(); + method @NonNull public android.app.appsearch.GenericDocument getParameters(); + method @NonNull public String getTargetPackageName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionRequest> CREATOR; + } + + public static final class ExecuteAppFunctionRequest.Builder { + ctor public ExecuteAppFunctionRequest.Builder(@NonNull String, @NonNull String); + method @NonNull public android.app.appfunctions.ExecuteAppFunctionRequest build(); + method @NonNull public android.app.appfunctions.ExecuteAppFunctionRequest.Builder setExtras(@NonNull android.os.Bundle); + method @NonNull public android.app.appfunctions.ExecuteAppFunctionRequest.Builder setParameters(@NonNull android.app.appsearch.GenericDocument); + } + +} + package android.app.assist { public class AssistContent implements android.os.Parcelable { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 445a57220757..fe792bc3a10b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -139,6 +139,8 @@ package android { field @FlaggedApi("com.android.window.flags.untrusted_embedding_any_app_permission") public static final String EMBED_ANY_APP_IN_UNTRUSTED_MODE = "android.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE"; field @FlaggedApi("android.content.pm.emergency_install_permission") public static final String EMERGENCY_INSTALL_PACKAGES = "android.permission.EMERGENCY_INSTALL_PACKAGES"; field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED"; + field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXECUTE_APP_FUNCTIONS = "android.permission.EXECUTE_APP_FUNCTIONS"; + field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXECUTE_APP_FUNCTIONS_TRUSTED = "android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED"; field public static final String EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS = "android.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS"; field public static final String FORCE_BACK = "android.permission.FORCE_BACK"; field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8dc9652db58c..177b859da0ad 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -941,7 +941,7 @@ package android.companion.virtual { method public int getAudioRecordingSessionId(int); method public int getDeviceIdForDisplayId(int); method public int getDevicePolicy(int, int); - method @FlaggedApi("android.companion.virtual.flags.interactive_screen_mirror") public boolean isVirtualDeviceOwnedMirrorDisplay(int); + method public boolean isVirtualDeviceOwnedMirrorDisplay(int); method public void playSoundEffect(int, int); } @@ -2579,9 +2579,10 @@ package android.os { @FlaggedApi("android.os.vibrator.vendor_vibration_effects") public static final class VibrationEffect.VendorEffect extends android.os.VibrationEffect { method @Nullable public long[] computeCreateWaveformOffOnTimingsOrNull(); + method public float getAdaptiveScale(); method public long getDuration(); method public int getEffectStrength(); - method public float getLinearScale(); + method public float getScale(); method @NonNull public android.os.PersistableBundle getVendorData(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.VendorEffect> CREATOR; diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 65acd49d44fa..91aa225039a4 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -1587,6 +1587,16 @@ public class ActivityOptions extends ComponentOptions { } } + /** @hide */ + public static boolean hasLaunchTargetContainer(ActivityOptions options) { + return options.getLaunchDisplayId() != INVALID_DISPLAY + || options.getLaunchTaskDisplayArea() != null + || options.getLaunchTaskDisplayAreaFeatureId() != FEATURE_UNDEFINED + || options.getLaunchRootTask() != null + || options.getLaunchTaskId() != -1 + || options.getLaunchTaskFragmentToken() != null; + } + /** * Gets whether the activity is to be launched into LockTask mode. * @return {@code true} if the activity is to be launched into LockTask mode. diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java index 81e9df66e18a..8370c2e522f3 100644 --- a/core/java/android/app/AppCompatTaskInfo.java +++ b/core/java/android/app/AppCompatTaskInfo.java @@ -95,6 +95,8 @@ public class AppCompatTaskInfo implements Parcelable { private static final int FLAG_FULLSCREEN_OVERRIDE_SYSTEM = FLAG_BASE << 7; /** Top activity flag for whether has activity has been overridden to fullscreen by user. */ private static final int FLAG_FULLSCREEN_OVERRIDE_USER = FLAG_BASE << 8; + /** Top activity flag for whether min aspect ratio of the activity has been overridden.*/ + public static final int FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE = FLAG_BASE << 9; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { @@ -108,7 +110,8 @@ public class AppCompatTaskInfo implements Parcelable { FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP, FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON, FLAG_FULLSCREEN_OVERRIDE_SYSTEM, - FLAG_FULLSCREEN_OVERRIDE_USER + FLAG_FULLSCREEN_OVERRIDE_USER, + FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE }) public @interface TopActivityFlag {} @@ -118,7 +121,7 @@ public class AppCompatTaskInfo implements Parcelable { @TopActivityFlag private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP | FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM - | FLAG_FULLSCREEN_OVERRIDE_USER; + | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE; @TopActivityFlag private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED @@ -301,6 +304,21 @@ public class AppCompatTaskInfo implements Parcelable { setTopActivityFlag(FLAG_LETTERBOXED, enable); } + /** + * @return {@code true} if the top activity's min aspect ratio has been overridden. + */ + public boolean hasMinAspectRatioOverride() { + return isTopActivityFlagEnabled(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE); + } + + /** + * Sets the top activity flag for whether the min aspect ratio of the activity has been + * overridden. + */ + public void setHasMinAspectRatioOverride(boolean enable) { + setTopActivityFlag(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, enable); + } + /** Clear all top activity flags and set to false. */ public void clearTopActivityFlags() { mTopActivityFlags = FLAG_UNDEFINED; @@ -392,6 +410,7 @@ public class AppCompatTaskInfo implements Parcelable { + " topActivityLetterboxAppHeight=" + topActivityLetterboxAppHeight + " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled() + " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled() + + " hasMinAspectRatioOverride=" + hasMinAspectRatioOverride() + " cameraCompatTaskInfo=" + cameraCompatTaskInfo.toString() + "}"; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 7e2a580bec73..90fba2962a23 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1160,7 +1160,7 @@ class ContextImpl extends Context { } mMainThread.getInstrumentation().execStartActivity( getOuterContext(), mMainThread.getApplicationThread(), null, - (Activity) null, intent, -1, options); + (Activity) null, intent, -1, applyLaunchDisplayIfNeeded(options)); } /** @hide */ @@ -1170,8 +1170,8 @@ class ContextImpl extends Context { ActivityTaskManager.getService().startActivityAsUser( mMainThread.getApplicationThread(), getOpPackageName(), getAttributionTag(), intent, intent.resolveTypeIfNeeded(getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, - user.getIdentifier()); + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, + applyLaunchDisplayIfNeeded(options), user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1194,7 +1194,8 @@ class ContextImpl extends Context { } return mMainThread.getInstrumentation().execStartActivitiesAsUser( getOuterContext(), mMainThread.getApplicationThread(), null, - (Activity) null, intents, options, userHandle.getIdentifier()); + (Activity) null, intents, applyLaunchDisplayIfNeeded(options), + userHandle.getIdentifier()); } @Override @@ -1208,7 +1209,26 @@ class ContextImpl extends Context { } mMainThread.getInstrumentation().execStartActivities( getOuterContext(), mMainThread.getApplicationThread(), null, - (Activity) null, intents, options); + (Activity) null, intents, applyLaunchDisplayIfNeeded(options)); + } + + private Bundle applyLaunchDisplayIfNeeded(@Nullable Bundle options) { + if (!isAssociatedWithDisplay()) { + // return if this Context has no associated display. + return options; + } + + final ActivityOptions activityOptions; + if (options != null) { + activityOptions = ActivityOptions.fromBundle(options); + if (ActivityOptions.hasLaunchTargetContainer(activityOptions)) { + // return if the options already has launching target. + return options; + } + } else { + activityOptions = ActivityOptions.makeBasic(); + } + return activityOptions.setLaunchDisplayId(getAssociatedDisplayId()).toBundle(); } @Override diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 5903a7ff619c..38f59adfcc1e 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1571,12 +1571,29 @@ public class WallpaperManager { */ @Nullable public Rect peekBitmapDimensions(@SetWallpaperFlags int which, boolean returnDefault) { + if (multiCrop()) { + return peekBitmapDimensionsAsUser(which, returnDefault, mContext.getUserId()); + } checkExactlyOneWallpaperFlagSet(which); return sGlobals.peekWallpaperDimensions(mContext, returnDefault, which, mContext.getUserId()); } /** + * Overload of {@link #peekBitmapDimensions(int, boolean)} with a userId argument. + * TODO(b/360120606): remove the SuppressWarnings + * @hide + */ + @SuppressWarnings("AndroidFrameworkContextUserId") + @FlaggedApi(FLAG_MULTI_CROP) + @Nullable + public Rect peekBitmapDimensionsAsUser(@SetWallpaperFlags int which, boolean returnDefault, + int userId) { + checkExactlyOneWallpaperFlagSet(which); + return sGlobals.peekWallpaperDimensions(mContext, returnDefault, which, userId); + } + + /** * For the current user, given a list of display sizes, return a list of rectangles representing * the area of the current wallpaper that would be shown for each of these sizes. * diff --git a/core/java/android/app/appfunctions/AppFunctionManager.java b/core/java/android/app/appfunctions/AppFunctionManager.java index a01e373c5e83..bf21549198f3 100644 --- a/core/java/android/app/appfunctions/AppFunctionManager.java +++ b/core/java/android/app/appfunctions/AppFunctionManager.java @@ -16,6 +16,9 @@ package android.app.appfunctions; +import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; + +import android.annotation.FlaggedApi; import android.annotation.SystemService; import android.content.Context; @@ -25,8 +28,8 @@ import android.content.Context; * <p>App function is a specific piece of functionality that an app offers to the system. These * functionalities can be integrated into various system features. * - * @hide */ +@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) @SystemService(Context.APP_FUNCTION_SERVICE) public final class AppFunctionManager { private final IAppFunctionManager mService; diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl new file mode 100644 index 000000000000..42ec45df8f25 --- /dev/null +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl @@ -0,0 +1,23 @@ + +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.app.appfunctions; + +import android.app.appfunctions.ExecuteAppFunctionAidlRequest; + +/** {@hide} */ +parcelable ExecuteAppFunctionAidlRequest;
\ No newline at end of file diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java new file mode 100644 index 000000000000..2f3c555d9465 --- /dev/null +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.appfunctions; + +import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; + + +import java.util.Objects; + +/** + * An internal request to execute an app function. + * + * @hide + */ +@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) +public final class ExecuteAppFunctionAidlRequest implements Parcelable { + + public static final Creator<ExecuteAppFunctionAidlRequest> CREATOR = + new Creator<ExecuteAppFunctionAidlRequest>() { + @Override + public ExecuteAppFunctionAidlRequest createFromParcel(Parcel in) { + ExecuteAppFunctionRequest clientRequest = + ExecuteAppFunctionRequest.CREATOR.createFromParcel(in); + UserHandle userHandle = + UserHandle.CREATOR.createFromParcel(in); + String callingPackage = in.readString8(); + return new ExecuteAppFunctionAidlRequest( + clientRequest, userHandle, callingPackage); + } + + @Override + public ExecuteAppFunctionAidlRequest[] newArray(int size) { + return new ExecuteAppFunctionAidlRequest[size]; + } + }; + + /** + * The client request to execute an app function. + */ + private final ExecuteAppFunctionRequest mClientRequest; + + /** + * The user handle of the user to execute the app function. + */ + private final UserHandle mUserHandle; + + /** + * The package name of the app that is requesting to execute the app function. + */ + private final String mCallingPackage; + + public ExecuteAppFunctionAidlRequest( + ExecuteAppFunctionRequest clientRequest, UserHandle userHandle, String callingPackage) { + this.mClientRequest = Objects.requireNonNull(clientRequest); + this.mUserHandle = Objects.requireNonNull(userHandle); + this.mCallingPackage = Objects.requireNonNull(callingPackage); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + mClientRequest.writeToParcel(dest, flags); + mUserHandle.writeToParcel(dest, flags); + dest.writeString8(mCallingPackage); + } + + /** + * Returns the client request to execute an app function. + */ + @NonNull + public ExecuteAppFunctionRequest getClientRequest() { + return mClientRequest; + } + + /** + * Returns the user handle of the user to execute the app function. + */ + @NonNull + public UserHandle getUserHandle() { + return mUserHandle; + } + + /** + * Returns the package name of the app that is requesting to execute the app function. + */ + @NonNull + public String getCallingPackage() { + return mCallingPackage; + } +} diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.aidl new file mode 100644 index 000000000000..a0b889e1bb68 --- /dev/null +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.app.appfunctions; + +import android.app.appfunctions.ExecuteAppFunctionRequest; + +parcelable ExecuteAppFunctionRequest;
\ No newline at end of file diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java new file mode 100644 index 000000000000..a50425e4db91 --- /dev/null +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.appfunctions; + + +import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.app.appsearch.GenericDocument; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * A request to execute an app function. + */ +@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) +public final class ExecuteAppFunctionRequest implements Parcelable { + @NonNull + public static final Creator<ExecuteAppFunctionRequest> CREATOR = + new Creator<>() { + @Override + public ExecuteAppFunctionRequest createFromParcel(Parcel parcel) { + String targetPackageName = parcel.readString8(); + String functionIdentifier = parcel.readString8(); + GenericDocument parameters; + parameters = GenericDocument.createFromParcel(parcel); + Bundle extras = parcel.readBundle(Bundle.class.getClassLoader()); + return new ExecuteAppFunctionRequest( + targetPackageName, functionIdentifier, extras, parameters); + } + + @Override + public ExecuteAppFunctionRequest[] newArray(int size) { + return new ExecuteAppFunctionRequest[size]; + } + }; + /** + * Returns the package name of the app that hosts the function. + */ + @NonNull + private final String mTargetPackageName; + /** + * Returns the unique string identifier of the app function to be executed. + * TODO(b/357551503): Document how callers can get the available function identifiers. + */ + @NonNull + private final String mFunctionIdentifier; + /** + * Returns additional metadata relevant to this function execution request. + */ + @NonNull + private final Bundle mExtras; + /** + * Returns the parameters required to invoke this function. Within this [GenericDocument], + * the property names are the names of the function parameters and the property values are the + * values of those parameters. + * + * <p>The document may have missing parameters. Developers are advised to implement defensive + * handling measures. + * + * TODO(b/357551503): Document how function parameters can be obtained for function execution + */ + @NonNull + private final GenericDocument mParameters; + + private ExecuteAppFunctionRequest( + @NonNull String targetPackageName, + @NonNull String functionIdentifier, + @NonNull Bundle extras, + @NonNull GenericDocument parameters) { + mTargetPackageName = Objects.requireNonNull(targetPackageName); + mFunctionIdentifier = Objects.requireNonNull(functionIdentifier); + mExtras = Objects.requireNonNull(extras); + mParameters = Objects.requireNonNull(parameters); + } + + /** + * Returns the package name of the app that hosts the function. + */ + @NonNull + public String getTargetPackageName() { + return mTargetPackageName; + } + + /** + * Returns the unique string identifier of the app function to be executed. + */ + @NonNull + public String getFunctionIdentifier() { + return mFunctionIdentifier; + } + + /** + * Returns the function parameters. The key is the parameter name, and the value is the + * parameter value. + * <p> + * The bundle may have missing parameters. Developers are advised to implement defensive + * handling measures. + */ + @NonNull + public GenericDocument getParameters() { + return mParameters; + } + + /** + * Returns the additional data relevant to this function execution. + */ + @NonNull + public Bundle getExtras() { + return mExtras; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString8(mTargetPackageName); + dest.writeString8(mFunctionIdentifier); + mParameters.writeToParcel(dest, flags); + dest.writeBundle(mExtras); + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Builder for {@link ExecuteAppFunctionRequest}. + */ + public static final class Builder { + @NonNull + private final String mTargetPackageName; + @NonNull + private final String mFunctionIdentifier; + @NonNull + private Bundle mExtras = Bundle.EMPTY; + @NonNull + private GenericDocument mParameters = new GenericDocument.Builder<>("", "", "").build(); + + public Builder(@NonNull String targetPackageName, @NonNull String functionIdentifier) { + mTargetPackageName = Objects.requireNonNull(targetPackageName); + mFunctionIdentifier = Objects.requireNonNull(functionIdentifier); + } + + /** + * Sets the additional data relevant to this function execution. + */ + @NonNull + public Builder setExtras(@NonNull Bundle extras) { + mExtras = Objects.requireNonNull(extras); + return this; + } + + /** + * Sets the function parameters. + */ + @NonNull + public Builder setParameters(@NonNull GenericDocument parameters) { + mParameters = Objects.requireNonNull(parameters); + return this; + } + + /** + * Builds the {@link ExecuteAppFunctionRequest}. + */ + @NonNull + public ExecuteAppFunctionRequest build() { + return new ExecuteAppFunctionRequest( + mTargetPackageName, mFunctionIdentifier, mExtras, mParameters); + } + } +} diff --git a/core/java/android/app/appfunctions/ServiceCallHelper.java b/core/java/android/app/appfunctions/ServiceCallHelper.java new file mode 100644 index 000000000000..cc882bd4ba4a --- /dev/null +++ b/core/java/android/app/appfunctions/ServiceCallHelper.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.appfunctions; + +import android.annotation.NonNull; +import android.content.Intent; +import android.os.UserHandle; + +/** + * Defines a contract for establishing temporary connections to services and executing operations + * within a specified timeout. Implementations of this interface provide mechanisms to ensure that + * services are properly unbound after the operation completes or a timeout occurs. + * + * @param <T> Class of wrapped service. + * @hide + */ +public interface ServiceCallHelper<T> { + + /** + * Initiates service binding and executes a provided method when the service connects. Unbinds + * the service after execution or upon timeout. Returns the result of the bindService API. + * + * <p>When the service connection was made successfully, it's the caller responsibility to + * report the usage is completed and can be unbound by calling {@link + * ServiceUsageCompleteListener#onCompleted()}. + * + * <p>This method includes a timeout mechanism to prevent the system from being stuck in a state + * where a service is bound indefinitely (for example, if the binder method never returns). This + * helps ensure that the calling app does not remain alive unnecessarily. + * + * @param intent An Intent object that describes the service that should be bound. + * @param bindFlags Flags used to control the binding process See {@link + * android.content.Context#bindService}. + * @param timeoutInMillis The maximum time in milliseconds to wait for the service connection. + * @param userHandle The UserHandle of the user for which the service should be bound. + * @param callback A callback to be invoked for various events. See {@link + * RunServiceCallCallback}. + */ + boolean runServiceCall( + @NonNull Intent intent, + int bindFlags, + long timeoutInMillis, + @NonNull UserHandle userHandle, + @NonNull RunServiceCallCallback<T> callback); + + /** An interface for clients to signal that they have finished using a bound service. */ + interface ServiceUsageCompleteListener { + /** + * Called when a client has finished using a bound service. This indicates that the service + * can be safely unbound. + */ + void onCompleted(); + } + + interface RunServiceCallCallback<T> { + /** + * Called when the service connection has been established. Uses {@code + * serviceUsageCompleteListener} to report finish using the connected service. + */ + void onServiceConnected( + @NonNull T service, + @NonNull ServiceUsageCompleteListener serviceUsageCompleteListener); + + /** Called when the service connection was failed to establish. */ + void onFailedToConnect(); + + /** + * Called when the whole operation(i.e. binding and the service call) takes longer than + * allowed. + */ + void onTimedOut(); + } +} diff --git a/core/java/android/app/appfunctions/ServiceCallHelperImpl.java b/core/java/android/app/appfunctions/ServiceCallHelperImpl.java new file mode 100644 index 000000000000..2e585467f437 --- /dev/null +++ b/core/java/android/app/appfunctions/ServiceCallHelperImpl.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.appfunctions; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.UserHandle; +import android.util.Log; + +import java.util.concurrent.Executor; +import java.util.function.Function; + +/** + * An implementation of {@link android.app.appfunctions.ServiceCallHelper} that that is based on + * {@link Context#bindService}. + * + * @param <T> Class of wrapped service. + * @hide + */ +public class ServiceCallHelperImpl<T> implements ServiceCallHelper<T> { + private static final String TAG = "AppFunctionsServiceCall"; + + @NonNull private final Context mContext; + @NonNull private final Function<IBinder, T> mInterfaceConverter; + private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final Executor mExecutor; + + /** + * @param interfaceConverter A function responsible for converting an IBinder object into the + * desired service interface. + * @param executor An Executor instance to dispatch callback. + * @param context The system context. + */ + public ServiceCallHelperImpl( + @NonNull Context context, + @NonNull Function<IBinder, T> interfaceConverter, + @NonNull Executor executor) { + mContext = context; + mInterfaceConverter = interfaceConverter; + mExecutor = executor; + } + + @Override + public boolean runServiceCall( + @NonNull Intent intent, + int bindFlags, + long timeoutInMillis, + @NonNull UserHandle userHandle, + @NonNull RunServiceCallCallback<T> callback) { + OneOffServiceConnection serviceConnection = + new OneOffServiceConnection( + intent, bindFlags, timeoutInMillis, userHandle, callback); + + return serviceConnection.bindAndRun(); + } + + private class OneOffServiceConnection + implements ServiceConnection, ServiceUsageCompleteListener { + private final Intent mIntent; + private final int mFlags; + private final long mTimeoutMillis; + private final UserHandle mUserHandle; + private final RunServiceCallCallback<T> mCallback; + private final Runnable mTimeoutCallback; + + OneOffServiceConnection( + @NonNull Intent intent, + int flags, + long timeoutMillis, + @NonNull UserHandle userHandle, + @NonNull RunServiceCallCallback<T> callback) { + mIntent = intent; + mFlags = flags; + mTimeoutMillis = timeoutMillis; + mCallback = callback; + mTimeoutCallback = + () -> + mExecutor.execute( + () -> { + safeUnbind(); + mCallback.onTimedOut(); + }); + mUserHandle = userHandle; + } + + public boolean bindAndRun() { + boolean bindServiceResult = + mContext.bindServiceAsUser(mIntent, this, mFlags, mUserHandle); + + if (bindServiceResult) { + mHandler.postDelayed(mTimeoutCallback, mTimeoutMillis); + } else { + safeUnbind(); + } + + return bindServiceResult; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + T serviceInterface = mInterfaceConverter.apply(service); + + mExecutor.execute(() -> mCallback.onServiceConnected(serviceInterface, this)); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + safeUnbind(); + mExecutor.execute(mCallback::onFailedToConnect); + } + + @Override + public void onBindingDied(ComponentName name) { + safeUnbind(); + mExecutor.execute(mCallback::onFailedToConnect); + } + + @Override + public void onNullBinding(ComponentName name) { + safeUnbind(); + mExecutor.execute(mCallback::onFailedToConnect); + } + + private void safeUnbind() { + try { + mHandler.removeCallbacks(mTimeoutCallback); + mContext.unbindService(this); + } catch (Exception ex) { + Log.w(TAG, "Failed to unbind", ex); + } + } + + @Override + public void onCompleted() { + safeUnbind(); + } + } +} diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java index 8b60580ec114..d07fb2508a49 100644 --- a/core/java/android/companion/virtual/VirtualDeviceManager.java +++ b/core/java/android/companion/virtual/VirtualDeviceManager.java @@ -531,7 +531,6 @@ public final class VirtualDeviceManager { * * @hide */ - @FlaggedApi(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR) @TestApi public boolean isVirtualDeviceOwnedMirrorDisplay(int displayId) { if (mService == null) { diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig index 91586b6bfae2..fc9c94dd5b0f 100644 --- a/core/java/android/companion/virtual/flags.aconfig +++ b/core/java/android/companion/virtual/flags.aconfig @@ -35,13 +35,6 @@ flag { } flag { - name: "consistent_display_flags" - namespace: "virtual_devices" - description: "Make virtual display flags consistent with display manager" - bug: "300905478" -} - -flag { name: "vdm_custom_ime" is_exported: true namespace: "virtual_devices" @@ -89,14 +82,6 @@ flag { } flag { - name: "interactive_screen_mirror" - is_exported: true - namespace: "virtual_devices" - description: "Enable interactive screen mirroring using Virtual Devices" - bug: "292212199" -} - -flag { name: "virtual_stylus" is_exported: true namespace: "virtual_devices" diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index 1fab3cffcebd..c7716e5a8d20 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -173,14 +173,47 @@ ] }, { - "name":"CtsPackageInstallerCUJTestCases", + "name": "CtsPackageInstallerCUJInstallationTestCases", "options":[ - { - "exclude-annotation":"androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation":"org.junit.Ignore" - } + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUninstallationTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateOwnerShipTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateSelfTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } ] } ] diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java index 61d87026b6e9..8975191b54c1 100644 --- a/core/java/android/hardware/biometrics/BiometricConstants.java +++ b/core/java/android/hardware/biometrics/BiometricConstants.java @@ -162,6 +162,13 @@ public interface BiometricConstants { * @hide */ int BIOMETRIC_ERROR_POWER_PRESSED = 19; + + /** + * Mandatory biometrics is not in effect. + * @hide + */ + int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20; + /** * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused * because the authentication attempt was unsuccessful. diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index de1cac47ff46..9bc46b9f382a 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -80,6 +80,20 @@ public class BiometricManager { BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; /** + * Lockout error. + * @hide + */ + public static final int BIOMETRIC_ERROR_LOCKOUT = + BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; + + /** + * Mandatory biometrics is not effective. + * @hide + */ + public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = + BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; + + /** * A security vulnerability has been discovered and the sensor is unavailable until a * security update has addressed this issue. This error can be received if for example, * authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the @@ -113,7 +127,9 @@ public class BiometricManager { BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED, BIOMETRIC_ERROR_NO_HARDWARE, - BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED}) + BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, + BIOMETRIC_ERROR_LOCKOUT, + BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE}) @Retention(RetentionPolicy.SOURCE) public @interface BiometricError {} diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 7353ddec74ac..a2d24f643bfb 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -504,6 +504,9 @@ public abstract class DisplayManagerInternal { public float dozeScreenBrightness; public int dozeScreenStateReason; + // Override that makes display use normal brightness while dozing. + public boolean useNormalBrightnessForDoze; + public DisplayPowerRequest() { policy = POLICY_BRIGHT; useProximitySensor = false; @@ -537,6 +540,7 @@ public abstract class DisplayManagerInternal { dozeScreenBrightness = other.dozeScreenBrightness; dozeScreenState = other.dozeScreenState; dozeScreenStateReason = other.dozeScreenStateReason; + useNormalBrightnessForDoze = other.useNormalBrightnessForDoze; } @Override @@ -561,7 +565,8 @@ public abstract class DisplayManagerInternal { && boostScreenBrightness == other.boostScreenBrightness && floatEquals(dozeScreenBrightness, other.dozeScreenBrightness) && dozeScreenState == other.dozeScreenState - && dozeScreenStateReason == other.dozeScreenStateReason; + && dozeScreenStateReason == other.dozeScreenStateReason + && useNormalBrightnessForDoze == other.useNormalBrightnessForDoze; } private boolean floatEquals(float f1, float f2) { @@ -587,7 +592,8 @@ public abstract class DisplayManagerInternal { + ", dozeScreenBrightness=" + dozeScreenBrightness + ", dozeScreenState=" + Display.stateToString(dozeScreenState) + ", dozeScreenStateReason=" - + Display.stateReasonToString(dozeScreenStateReason); + + Display.stateReasonToString(dozeScreenStateReason) + + ", useNormalBrightnessForDoze=" + useNormalBrightnessForDoze; } public static String policyToString(int policy) { diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index 98e11375f077..83f268517dab 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -25,7 +25,7 @@ import android.hardware.input.IInputDeviceBatteryListener; import android.hardware.input.IInputDeviceBatteryState; import android.hardware.input.IKeyboardBacklightListener; import android.hardware.input.IKeyboardBacklightState; -import android.hardware.input.IKeyboardSystemShortcutListener; +import android.hardware.input.IKeyGestureEventListener; import android.hardware.input.IStickyModifierStateListener; import android.hardware.input.ITabletModeChangedListener; import android.hardware.input.KeyboardLayoutSelectionResult; @@ -241,13 +241,13 @@ interface IInputManager { KeyGlyphMap getKeyGlyphMap(int deviceId); - @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS") + @EnforcePermission("MANAGE_KEY_GESTURES") @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " - + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)") - void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener); + + "android.Manifest.permission.MANAGE_KEY_GESTURES)") + void registerKeyGestureEventListener(IKeyGestureEventListener listener); - @EnforcePermission("MONITOR_KEYBOARD_SYSTEM_SHORTCUTS") + @EnforcePermission("MANAGE_KEY_GESTURES") @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " - + "android.Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS)") - void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener); + + "android.Manifest.permission.MANAGE_KEY_GESTURES)") + void unregisterKeyGestureEventListener(IKeyGestureEventListener listener); } diff --git a/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl b/core/java/android/hardware/input/IKeyGestureEventListener.aidl index 8d44917845f4..2c430f1a1c9d 100644 --- a/core/java/android/hardware/input/IKeyboardSystemShortcutListener.aidl +++ b/core/java/android/hardware/input/IKeyGestureEventListener.aidl @@ -17,11 +17,10 @@ package android.hardware.input; /** @hide */ -oneway interface IKeyboardSystemShortcutListener { +oneway interface IKeyGestureEventListener { /** - * Called when the keyboard system shortcut is triggered. + * Called when a key gesture event occurs. */ - void onKeyboardSystemShortcutTriggered(int deviceId, in int[] keycodes, int modifierState, - int shortcut); + void onKeyGestureEvent(int deviceId, in int[] keycodes, int modifierState, int shortcut); } diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 6bc522b2b386..04cfcd880f52 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -1378,33 +1378,31 @@ public final class InputManager { } /** - * Registers a keyboard system shortcut listener for {@link KeyboardSystemShortcut} being - * triggered. + * Registers a key gesture event listener for {@link KeyGestureEvent} being triggered. * * @param executor an executor on which the callback will be called - * @param listener the {@link KeyboardSystemShortcutListener} + * @param listener the {@link KeyGestureEventListener} * @throws IllegalArgumentException if {@code listener} has already been registered previously. * @throws NullPointerException if {@code listener} or {@code executor} is null. * @hide - * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener) + * @see #unregisterKeyGestureEventListener(KeyGestureEventListener) */ - @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - public void registerKeyboardSystemShortcutListener(@NonNull Executor executor, - @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException { - mGlobal.registerKeyboardSystemShortcutListener(executor, listener); + @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) + public void registerKeyGestureEventListener(@NonNull Executor executor, + @NonNull KeyGestureEventListener listener) throws IllegalArgumentException { + mGlobal.registerKeyGestureEventListener(executor, listener); } /** - * Unregisters a previously added keyboard system shortcut listener. + * Unregisters a previously added key gesture event listener. * - * @param listener the {@link KeyboardSystemShortcutListener} + * @param listener the {@link KeyGestureEventListener} * @hide - * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener) + * @see #registerKeyGestureEventListener(Executor, KeyGestureEventListener) */ - @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - public void unregisterKeyboardSystemShortcutListener( - @NonNull KeyboardSystemShortcutListener listener) { - mGlobal.unregisterKeyboardSystemShortcutListener(listener); + @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) + public void unregisterKeyGestureEventListener(@NonNull KeyGestureEventListener listener) { + mGlobal.unregisterKeyGestureEventListener(listener); } /** @@ -1510,19 +1508,18 @@ public final class InputManager { } /** - * A callback used to be notified about keyboard system shortcuts being triggered. + * A callback used to notify about key gesture event on completion. * - * @see #registerKeyboardSystemShortcutListener(Executor, KeyboardSystemShortcutListener) - * @see #unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener) + * @see #registerKeyGestureEventListener(Executor, KeyGestureEventListener) + * @see #unregisterKeyGestureEventListener(KeyGestureEventListener) * @hide */ - public interface KeyboardSystemShortcutListener { + public interface KeyGestureEventListener { /** - * Called when a keyboard system shortcut is triggered. + * Called when a key gesture event occurs. * - * @param systemShortcut the shortcut info about the shortcut that was triggered. + * @param event the gesture event that occurred. */ - void onKeyboardSystemShortcutTriggered(int deviceId, - @NonNull KeyboardSystemShortcut systemShortcut); + void onKeyGestureEvent(@NonNull KeyGestureEvent event); } } diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java index f7fa5577a047..03cf7c5f926c 100644 --- a/core/java/android/hardware/input/InputManagerGlobal.java +++ b/core/java/android/hardware/input/InputManagerGlobal.java @@ -25,8 +25,8 @@ import android.hardware.BatteryState; import android.hardware.SensorManager; import android.hardware.input.InputManager.InputDeviceBatteryListener; import android.hardware.input.InputManager.InputDeviceListener; +import android.hardware.input.InputManager.KeyGestureEventListener; import android.hardware.input.InputManager.KeyboardBacklightListener; -import android.hardware.input.InputManager.KeyboardSystemShortcutListener; import android.hardware.input.InputManager.OnTabletModeChangedListener; import android.hardware.input.InputManager.StickyModifierStateListener; import android.hardware.lights.Light; @@ -111,13 +111,13 @@ public final class InputManagerGlobal { @Nullable private IStickyModifierStateListener mStickyModifierStateListener; - private final Object mKeyboardSystemShortcutListenerLock = new Object(); - @GuardedBy("mKeyboardSystemShortcutListenerLock") + private final Object mKeyGestureEventListenerLock = new Object(); + @GuardedBy("mKeyGestureEventListenerLock") @Nullable - private ArrayList<KeyboardSystemShortcutListenerDelegate> mKeyboardSystemShortcutListeners; - @GuardedBy("mKeyboardSystemShortcutListenerLock") + private ArrayList<KeyGestureEventListenerDelegate> mKeyGestureEventListeners; + @GuardedBy("mKeyGestureEventListenerLock") @Nullable - private IKeyboardSystemShortcutListener mKeyboardSystemShortcutListener; + private IKeyGestureEventListener mKeyGestureEventListener; // InputDeviceSensorManager gets notified synchronously from the binder thread when input // devices change, so it must be synchronized with the input device listeners. @@ -1064,94 +1064,92 @@ public final class InputManagerGlobal { } } - private static final class KeyboardSystemShortcutListenerDelegate { - final KeyboardSystemShortcutListener mListener; + private static final class KeyGestureEventListenerDelegate { + final KeyGestureEventListener mListener; final Executor mExecutor; - KeyboardSystemShortcutListenerDelegate(KeyboardSystemShortcutListener listener, + KeyGestureEventListenerDelegate(KeyGestureEventListener listener, Executor executor) { mListener = listener; mExecutor = executor; } - void onKeyboardSystemShortcutTriggered(int deviceId, - KeyboardSystemShortcut systemShortcut) { - mExecutor.execute(() -> - mListener.onKeyboardSystemShortcutTriggered(deviceId, systemShortcut)); + void onKeyGestureEvent(KeyGestureEvent event) { + mExecutor.execute(() -> mListener.onKeyGestureEvent(event)); } } - private class LocalKeyboardSystemShortcutListener extends IKeyboardSystemShortcutListener.Stub { + private class LocalKeyGestureEventListener extends IKeyGestureEventListener.Stub { @Override - public void onKeyboardSystemShortcutTriggered(int deviceId, int[] keycodes, - int modifierState, int shortcut) { - synchronized (mKeyboardSystemShortcutListenerLock) { - if (mKeyboardSystemShortcutListeners == null) return; - final int numListeners = mKeyboardSystemShortcutListeners.size(); + public void onKeyGestureEvent(int deviceId, int[] keycodes, int modifierState, + int gestureType) { + synchronized (mKeyGestureEventListenerLock) { + if (mKeyGestureEventListeners == null) return; + final int numListeners = mKeyGestureEventListeners.size(); for (int i = 0; i < numListeners; i++) { - mKeyboardSystemShortcutListeners.get(i) - .onKeyboardSystemShortcutTriggered(deviceId, - new KeyboardSystemShortcut(keycodes, modifierState, shortcut)); + mKeyGestureEventListeners.get(i) + .onKeyGestureEvent( + new KeyGestureEvent(deviceId, keycodes, modifierState, + gestureType)); } } } } /** - * @see InputManager#registerKeyboardSystemShortcutListener(Executor, - * KeyboardSystemShortcutListener) + * @see InputManager#registerKeyGestureEventListener(Executor, + * KeyGestureEventListener) */ - @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - void registerKeyboardSystemShortcutListener(@NonNull Executor executor, - @NonNull KeyboardSystemShortcutListener listener) throws IllegalArgumentException { + @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) + void registerKeyGestureEventListener(@NonNull Executor executor, + @NonNull KeyGestureEventListener listener) throws IllegalArgumentException { Objects.requireNonNull(executor, "executor should not be null"); Objects.requireNonNull(listener, "listener should not be null"); - synchronized (mKeyboardSystemShortcutListenerLock) { - if (mKeyboardSystemShortcutListener == null) { - mKeyboardSystemShortcutListeners = new ArrayList<>(); - mKeyboardSystemShortcutListener = new LocalKeyboardSystemShortcutListener(); + synchronized (mKeyGestureEventListenerLock) { + if (mKeyGestureEventListener == null) { + mKeyGestureEventListeners = new ArrayList<>(); + mKeyGestureEventListener = new LocalKeyGestureEventListener(); try { - mIm.registerKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener); + mIm.registerKeyGestureEventListener(mKeyGestureEventListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - final int numListeners = mKeyboardSystemShortcutListeners.size(); + final int numListeners = mKeyGestureEventListeners.size(); for (int i = 0; i < numListeners; i++) { - if (mKeyboardSystemShortcutListeners.get(i).mListener == listener) { + if (mKeyGestureEventListeners.get(i).mListener == listener) { throw new IllegalArgumentException("Listener has already been registered!"); } } - KeyboardSystemShortcutListenerDelegate delegate = - new KeyboardSystemShortcutListenerDelegate(listener, executor); - mKeyboardSystemShortcutListeners.add(delegate); + KeyGestureEventListenerDelegate delegate = + new KeyGestureEventListenerDelegate(listener, executor); + mKeyGestureEventListeners.add(delegate); } } /** - * @see InputManager#unregisterKeyboardSystemShortcutListener(KeyboardSystemShortcutListener) + * @see InputManager#unregisterKeyGestureEventListener(KeyGestureEventListener) */ - @RequiresPermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - void unregisterKeyboardSystemShortcutListener( - @NonNull KeyboardSystemShortcutListener listener) { + @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) + void unregisterKeyGestureEventListener(@NonNull KeyGestureEventListener listener) { Objects.requireNonNull(listener, "listener should not be null"); - synchronized (mKeyboardSystemShortcutListenerLock) { - if (mKeyboardSystemShortcutListeners == null) { + synchronized (mKeyGestureEventListenerLock) { + if (mKeyGestureEventListeners == null) { return; } - mKeyboardSystemShortcutListeners.removeIf((delegate) -> delegate.mListener == listener); - if (mKeyboardSystemShortcutListeners.isEmpty()) { + mKeyGestureEventListeners.removeIf((delegate) -> delegate.mListener == listener); + if (mKeyGestureEventListeners.isEmpty()) { try { - mIm.unregisterKeyboardSystemShortcutListener(mKeyboardSystemShortcutListener); + mIm.unregisterKeyGestureEventListener(mKeyGestureEventListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - mKeyboardSystemShortcutListeners = null; - mKeyboardSystemShortcutListener = null; + mKeyGestureEventListeners = null; + mKeyGestureEventListener = null; } } } diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java index d85e41d19c68..c5d0caf228d2 100644 --- a/core/java/android/hardware/input/InputSettings.java +++ b/core/java/android/hardware/input/InputSettings.java @@ -336,6 +336,39 @@ public class InputSettings { } /** + * Returns true if the touchpad visualizer is allowed to appear. + * + * @param context The application context. + * @return Whether it is allowed to show touchpad visualizer or not. + * + * @hide + */ + public static boolean useTouchpadVisualizer(@NonNull Context context) { + if (!isTouchpadVisualizerFeatureFlagEnabled()) { + return false; + } + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.TOUCHPAD_VISUALIZER, 0, UserHandle.USER_CURRENT) == 1; + } + + /** + * Sets the touchpad visualizer behaviour. + * + * @param context The application context. + * @param enabled Will enable touchpad visualizer if true, disable it if false + * + * @hide + */ + @RequiresPermission(Manifest.permission.WRITE_SETTINGS) + public static void setTouchpadVisualizer(@NonNull Context context, boolean enabled) { + if (!isTouchpadVisualizerFeatureFlagEnabled()) { + return; + } + Settings.System.putIntForUser(context.getContentResolver(), + Settings.System.TOUCHPAD_VISUALIZER, enabled ? 1 : 0, UserHandle.USER_CURRENT); + } + + /** * Returns true if the touchpad should allow tap dragging. * * The returned value only applies to gesture-compatible touchpads. diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java new file mode 100644 index 000000000000..7a8dd3395d21 --- /dev/null +++ b/core/java/android/hardware/input/KeyGestureEvent.java @@ -0,0 +1,531 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.util.DataClass; +import com.android.internal.util.FrameworkStatsLog; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Provides information about the keyboard gesture event being triggered by an external keyboard. + * + * @hide + */ +@DataClass(genToString = true, genEqualsHashCode = true) +public class KeyGestureEvent { + + private final int mDeviceId; + @NonNull + private final int[] mKeycodes; + private final int mModifierState; + @KeyGestureType + private final int mKeyGestureType; + + + public static final int KEY_GESTURE_TYPE_UNSPECIFIED = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED; + public static final int KEY_GESTURE_TYPE_HOME = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME; + public static final int KEY_GESTURE_TYPE_RECENT_APPS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS; + public static final int KEY_GESTURE_TYPE_BACK = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK; + public static final int KEY_GESTURE_TYPE_APP_SWITCH = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH; + public static final int KEY_GESTURE_TYPE_LAUNCH_ASSISTANT = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT; + public static final int KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT; + public static final int KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS; + public static final int KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL; + public static final int KEY_GESTURE_TYPE_TOGGLE_TASKBAR = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR; + public static final int KEY_GESTURE_TYPE_TAKE_SCREENSHOT = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT; + public static final int KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER; + public static final int KEY_GESTURE_TYPE_BRIGHTNESS_UP = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP; + public static final int KEY_GESTURE_TYPE_BRIGHTNESS_DOWN = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN; + public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP; + public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN; + public static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE; + public static final int KEY_GESTURE_TYPE_VOLUME_UP = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP; + public static final int KEY_GESTURE_TYPE_VOLUME_DOWN = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN; + public static final int KEY_GESTURE_TYPE_VOLUME_MUTE = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE; + public static final int KEY_GESTURE_TYPE_ALL_APPS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS; + public static final int KEY_GESTURE_TYPE_LAUNCH_SEARCH = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH; + public static final int KEY_GESTURE_TYPE_LANGUAGE_SWITCH = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH; + public static final int KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS; + public static final int KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK; + public static final int KEY_GESTURE_TYPE_SYSTEM_MUTE = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE; + public static final int KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION; + public static final int KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS; + public static final int KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT; + public static final int KEY_GESTURE_TYPE_LOCK_SCREEN = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN; + public static final int KEY_GESTURE_TYPE_OPEN_NOTES = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES; + public static final int KEY_GESTURE_TYPE_TOGGLE_POWER = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER; + public static final int KEY_GESTURE_TYPE_SYSTEM_NAVIGATION = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION; + public static final int KEY_GESTURE_TYPE_SLEEP = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP; + public static final int KEY_GESTURE_TYPE_WAKEUP = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP; + public static final int KEY_GESTURE_TYPE_MEDIA_KEY = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER; + public static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS; + public static final int KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME; + public static final int KEY_GESTURE_TYPE_DESKTOP_MODE = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE; + public static final int KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION = + FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION; + + + + // Code below generated by codegen v1.0.23. + // + // DO NOT MODIFY! + // CHECKSTYLE:OFF Generated code + // + // To regenerate run: + // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/KeyGestureEvent.java + // + // To exclude the generated code from IntelliJ auto-formatting enable (one-time): + // Settings > Editor > Code Style > Formatter Control + //@formatter:off + + + @IntDef(prefix = "KEY_GESTURE_TYPE_", value = { + KEY_GESTURE_TYPE_UNSPECIFIED, + KEY_GESTURE_TYPE_HOME, + KEY_GESTURE_TYPE_RECENT_APPS, + KEY_GESTURE_TYPE_BACK, + KEY_GESTURE_TYPE_APP_SWITCH, + KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, + KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT, + KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS, + KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, + KEY_GESTURE_TYPE_TOGGLE_TASKBAR, + KEY_GESTURE_TYPE_TAKE_SCREENSHOT, + KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER, + KEY_GESTURE_TYPE_BRIGHTNESS_UP, + KEY_GESTURE_TYPE_BRIGHTNESS_DOWN, + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP, + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN, + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE, + KEY_GESTURE_TYPE_VOLUME_UP, + KEY_GESTURE_TYPE_VOLUME_DOWN, + KEY_GESTURE_TYPE_VOLUME_MUTE, + KEY_GESTURE_TYPE_ALL_APPS, + KEY_GESTURE_TYPE_LAUNCH_SEARCH, + KEY_GESTURE_TYPE_LANGUAGE_SWITCH, + KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, + KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, + KEY_GESTURE_TYPE_SYSTEM_MUTE, + KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION, + KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS, + KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT, + KEY_GESTURE_TYPE_LOCK_SCREEN, + KEY_GESTURE_TYPE_OPEN_NOTES, + KEY_GESTURE_TYPE_TOGGLE_POWER, + KEY_GESTURE_TYPE_SYSTEM_NAVIGATION, + KEY_GESTURE_TYPE_SLEEP, + KEY_GESTURE_TYPE_WAKEUP, + KEY_GESTURE_TYPE_MEDIA_KEY, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER, + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS, + KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME, + KEY_GESTURE_TYPE_DESKTOP_MODE, + KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION + }) + @Retention(RetentionPolicy.SOURCE) + @DataClass.Generated.Member + public @interface KeyGestureType {} + + @DataClass.Generated.Member + public static String keyGestureTypeToString(@KeyGestureType int value) { + switch (value) { + case KEY_GESTURE_TYPE_UNSPECIFIED: + return "KEY_GESTURE_TYPE_UNSPECIFIED"; + case KEY_GESTURE_TYPE_HOME: + return "KEY_GESTURE_TYPE_HOME"; + case KEY_GESTURE_TYPE_RECENT_APPS: + return "KEY_GESTURE_TYPE_RECENT_APPS"; + case KEY_GESTURE_TYPE_BACK: + return "KEY_GESTURE_TYPE_BACK"; + case KEY_GESTURE_TYPE_APP_SWITCH: + return "KEY_GESTURE_TYPE_APP_SWITCH"; + case KEY_GESTURE_TYPE_LAUNCH_ASSISTANT: + return "KEY_GESTURE_TYPE_LAUNCH_ASSISTANT"; + case KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT: + return "KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT"; + case KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS: + return "KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS"; + case KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL: + return "KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL"; + case KEY_GESTURE_TYPE_TOGGLE_TASKBAR: + return "KEY_GESTURE_TYPE_TOGGLE_TASKBAR"; + case KEY_GESTURE_TYPE_TAKE_SCREENSHOT: + return "KEY_GESTURE_TYPE_TAKE_SCREENSHOT"; + case KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER: + return "KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER"; + case KEY_GESTURE_TYPE_BRIGHTNESS_UP: + return "KEY_GESTURE_TYPE_BRIGHTNESS_UP"; + case KEY_GESTURE_TYPE_BRIGHTNESS_DOWN: + return "KEY_GESTURE_TYPE_BRIGHTNESS_DOWN"; + case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: + return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP"; + case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: + return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN"; + case KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: + return "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE"; + case KEY_GESTURE_TYPE_VOLUME_UP: + return "KEY_GESTURE_TYPE_VOLUME_UP"; + case KEY_GESTURE_TYPE_VOLUME_DOWN: + return "KEY_GESTURE_TYPE_VOLUME_DOWN"; + case KEY_GESTURE_TYPE_VOLUME_MUTE: + return "KEY_GESTURE_TYPE_VOLUME_MUTE"; + case KEY_GESTURE_TYPE_ALL_APPS: + return "KEY_GESTURE_TYPE_ALL_APPS"; + case KEY_GESTURE_TYPE_LAUNCH_SEARCH: + return "KEY_GESTURE_TYPE_LAUNCH_SEARCH"; + case KEY_GESTURE_TYPE_LANGUAGE_SWITCH: + return "KEY_GESTURE_TYPE_LANGUAGE_SWITCH"; + case KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS: + return "KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS"; + case KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: + return "KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK"; + case KEY_GESTURE_TYPE_SYSTEM_MUTE: + return "KEY_GESTURE_TYPE_SYSTEM_MUTE"; + case KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION: + return "KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION"; + case KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS: + return "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS"; + case KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT: + return "KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT"; + case KEY_GESTURE_TYPE_LOCK_SCREEN: + return "KEY_GESTURE_TYPE_LOCK_SCREEN"; + case KEY_GESTURE_TYPE_OPEN_NOTES: + return "KEY_GESTURE_TYPE_OPEN_NOTES"; + case KEY_GESTURE_TYPE_TOGGLE_POWER: + return "KEY_GESTURE_TYPE_TOGGLE_POWER"; + case KEY_GESTURE_TYPE_SYSTEM_NAVIGATION: + return "KEY_GESTURE_TYPE_SYSTEM_NAVIGATION"; + case KEY_GESTURE_TYPE_SLEEP: + return "KEY_GESTURE_TYPE_SLEEP"; + case KEY_GESTURE_TYPE_WAKEUP: + return "KEY_GESTURE_TYPE_WAKEUP"; + case KEY_GESTURE_TYPE_MEDIA_KEY: + return "KEY_GESTURE_TYPE_MEDIA_KEY"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER"; + case KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS: + return "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS"; + case KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME: + return "KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME"; + case KEY_GESTURE_TYPE_DESKTOP_MODE: + return "KEY_GESTURE_TYPE_DESKTOP_MODE"; + case KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION: + return "KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION"; + default: return Integer.toHexString(value); + } + } + + @DataClass.Generated.Member + public KeyGestureEvent( + int deviceId, + @NonNull int[] keycodes, + int modifierState, + @KeyGestureType int keyGestureType) { + this.mDeviceId = deviceId; + this.mKeycodes = keycodes; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mKeycodes); + this.mModifierState = modifierState; + this.mKeyGestureType = keyGestureType; + + if (!(mKeyGestureType == KEY_GESTURE_TYPE_UNSPECIFIED) + && !(mKeyGestureType == KEY_GESTURE_TYPE_HOME) + && !(mKeyGestureType == KEY_GESTURE_TYPE_RECENT_APPS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_BACK) + && !(mKeyGestureType == KEY_GESTURE_TYPE_APP_SWITCH) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_ASSISTANT) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_TASKBAR) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TAKE_SCREENSHOT) + && !(mKeyGestureType == KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER) + && !(mKeyGestureType == KEY_GESTURE_TYPE_BRIGHTNESS_UP) + && !(mKeyGestureType == KEY_GESTURE_TYPE_BRIGHTNESS_DOWN) + && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP) + && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN) + && !(mKeyGestureType == KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE) + && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_UP) + && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_DOWN) + && !(mKeyGestureType == KEY_GESTURE_TYPE_VOLUME_MUTE) + && !(mKeyGestureType == KEY_GESTURE_TYPE_ALL_APPS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_SEARCH) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LANGUAGE_SWITCH) + && !(mKeyGestureType == KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK) + && !(mKeyGestureType == KEY_GESTURE_TYPE_SYSTEM_MUTE) + && !(mKeyGestureType == KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION) + && !(mKeyGestureType == KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LOCK_SCREEN) + && !(mKeyGestureType == KEY_GESTURE_TYPE_OPEN_NOTES) + && !(mKeyGestureType == KEY_GESTURE_TYPE_TOGGLE_POWER) + && !(mKeyGestureType == KEY_GESTURE_TYPE_SYSTEM_NAVIGATION) + && !(mKeyGestureType == KEY_GESTURE_TYPE_SLEEP) + && !(mKeyGestureType == KEY_GESTURE_TYPE_WAKEUP) + && !(mKeyGestureType == KEY_GESTURE_TYPE_MEDIA_KEY) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS) + && !(mKeyGestureType == KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME) + && !(mKeyGestureType == KEY_GESTURE_TYPE_DESKTOP_MODE) + && !(mKeyGestureType == KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION)) { + throw new java.lang.IllegalArgumentException( + "keyGestureType was " + mKeyGestureType + " but must be one of: " + + "KEY_GESTURE_TYPE_UNSPECIFIED(" + KEY_GESTURE_TYPE_UNSPECIFIED + "), " + + "KEY_GESTURE_TYPE_HOME(" + KEY_GESTURE_TYPE_HOME + "), " + + "KEY_GESTURE_TYPE_RECENT_APPS(" + KEY_GESTURE_TYPE_RECENT_APPS + "), " + + "KEY_GESTURE_TYPE_BACK(" + KEY_GESTURE_TYPE_BACK + "), " + + "KEY_GESTURE_TYPE_APP_SWITCH(" + KEY_GESTURE_TYPE_APP_SWITCH + "), " + + "KEY_GESTURE_TYPE_LAUNCH_ASSISTANT(" + KEY_GESTURE_TYPE_LAUNCH_ASSISTANT + "), " + + "KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT(" + KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT + "), " + + "KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS(" + KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS + "), " + + "KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL(" + KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL + "), " + + "KEY_GESTURE_TYPE_TOGGLE_TASKBAR(" + KEY_GESTURE_TYPE_TOGGLE_TASKBAR + "), " + + "KEY_GESTURE_TYPE_TAKE_SCREENSHOT(" + KEY_GESTURE_TYPE_TAKE_SCREENSHOT + "), " + + "KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER(" + KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER + "), " + + "KEY_GESTURE_TYPE_BRIGHTNESS_UP(" + KEY_GESTURE_TYPE_BRIGHTNESS_UP + "), " + + "KEY_GESTURE_TYPE_BRIGHTNESS_DOWN(" + KEY_GESTURE_TYPE_BRIGHTNESS_DOWN + "), " + + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP + "), " + + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN + "), " + + "KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE(" + KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE + "), " + + "KEY_GESTURE_TYPE_VOLUME_UP(" + KEY_GESTURE_TYPE_VOLUME_UP + "), " + + "KEY_GESTURE_TYPE_VOLUME_DOWN(" + KEY_GESTURE_TYPE_VOLUME_DOWN + "), " + + "KEY_GESTURE_TYPE_VOLUME_MUTE(" + KEY_GESTURE_TYPE_VOLUME_MUTE + "), " + + "KEY_GESTURE_TYPE_ALL_APPS(" + KEY_GESTURE_TYPE_ALL_APPS + "), " + + "KEY_GESTURE_TYPE_LAUNCH_SEARCH(" + KEY_GESTURE_TYPE_LAUNCH_SEARCH + "), " + + "KEY_GESTURE_TYPE_LANGUAGE_SWITCH(" + KEY_GESTURE_TYPE_LANGUAGE_SWITCH + "), " + + "KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS(" + KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS + "), " + + "KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK(" + KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK + "), " + + "KEY_GESTURE_TYPE_SYSTEM_MUTE(" + KEY_GESTURE_TYPE_SYSTEM_MUTE + "), " + + "KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION(" + KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION + "), " + + "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS(" + KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS + "), " + + "KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT(" + KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT + "), " + + "KEY_GESTURE_TYPE_LOCK_SCREEN(" + KEY_GESTURE_TYPE_LOCK_SCREEN + "), " + + "KEY_GESTURE_TYPE_OPEN_NOTES(" + KEY_GESTURE_TYPE_OPEN_NOTES + "), " + + "KEY_GESTURE_TYPE_TOGGLE_POWER(" + KEY_GESTURE_TYPE_TOGGLE_POWER + "), " + + "KEY_GESTURE_TYPE_SYSTEM_NAVIGATION(" + KEY_GESTURE_TYPE_SYSTEM_NAVIGATION + "), " + + "KEY_GESTURE_TYPE_SLEEP(" + KEY_GESTURE_TYPE_SLEEP + "), " + + "KEY_GESTURE_TYPE_WAKEUP(" + KEY_GESTURE_TYPE_WAKEUP + "), " + + "KEY_GESTURE_TYPE_MEDIA_KEY(" + KEY_GESTURE_TYPE_MEDIA_KEY + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER + "), " + + "KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS(" + KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS + "), " + + "KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME(" + KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME + "), " + + "KEY_GESTURE_TYPE_DESKTOP_MODE(" + KEY_GESTURE_TYPE_DESKTOP_MODE + "), " + + "KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION(" + KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION + ")"); + } + + + // onConstructed(); // You can define this method to get a callback + } + + @DataClass.Generated.Member + public int getDeviceId() { + return mDeviceId; + } + + @DataClass.Generated.Member + public @NonNull int[] getKeycodes() { + return mKeycodes; + } + + @DataClass.Generated.Member + public int getModifierState() { + return mModifierState; + } + + @DataClass.Generated.Member + public @KeyGestureType int getKeyGestureType() { + return mKeyGestureType; + } + + @Override + @DataClass.Generated.Member + public String toString() { + // You can override field toString logic by defining methods like: + // String fieldNameToString() { ... } + + return "KeyGestureEvent { " + + "deviceId = " + mDeviceId + ", " + + "keycodes = " + java.util.Arrays.toString(mKeycodes) + ", " + + "modifierState = " + mModifierState + ", " + + "keyGestureType = " + keyGestureTypeToString(mKeyGestureType) + + " }"; + } + + @Override + @DataClass.Generated.Member + public boolean equals(@Nullable Object o) { + // You can override field equality logic by defining either of the methods like: + // boolean fieldNameEquals(KeyGestureEvent other) { ... } + // boolean fieldNameEquals(FieldType otherValue) { ... } + + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + @SuppressWarnings("unchecked") + KeyGestureEvent that = (KeyGestureEvent) o; + //noinspection PointlessBooleanExpression + return true + && mDeviceId == that.mDeviceId + && java.util.Arrays.equals(mKeycodes, that.mKeycodes) + && mModifierState == that.mModifierState + && mKeyGestureType == that.mKeyGestureType; + } + + @Override + @DataClass.Generated.Member + public int hashCode() { + // You can override field hashCode logic by defining methods like: + // int fieldNameHashCode() { ... } + + int _hash = 1; + _hash = 31 * _hash + mDeviceId; + _hash = 31 * _hash + java.util.Arrays.hashCode(mKeycodes); + _hash = 31 * _hash + mModifierState; + _hash = 31 * _hash + mKeyGestureType; + return _hash; + } + + @DataClass.Generated( + time = 1723409092192L, + codegenVersion = "1.0.23", + sourceFile = "frameworks/base/core/java/android/hardware/input/KeyGestureEvent.java", + inputSignatures = "private final int mDeviceId\nprivate final @android.annotation.NonNull int[] mKeycodes\nprivate final int mModifierState\nprivate final @android.hardware.input.KeyGestureEvent.KeyGestureType int mKeyGestureType\npublic static final int KEY_GESTURE_TYPE_UNSPECIFIED\npublic static final int KEY_GESTURE_TYPE_HOME\npublic static final int KEY_GESTURE_TYPE_RECENT_APPS\npublic static final int KEY_GESTURE_TYPE_BACK\npublic static final int KEY_GESTURE_TYPE_APP_SWITCH\npublic static final int KEY_GESTURE_TYPE_LAUNCH_ASSISTANT\npublic static final int KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT\npublic static final int KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS\npublic static final int KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL\npublic static final int KEY_GESTURE_TYPE_TOGGLE_TASKBAR\npublic static final int KEY_GESTURE_TYPE_TAKE_SCREENSHOT\npublic static final int KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER\npublic static final int KEY_GESTURE_TYPE_BRIGHTNESS_UP\npublic static final int KEY_GESTURE_TYPE_BRIGHTNESS_DOWN\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN\npublic static final int KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE\npublic static final int KEY_GESTURE_TYPE_VOLUME_UP\npublic static final int KEY_GESTURE_TYPE_VOLUME_DOWN\npublic static final int KEY_GESTURE_TYPE_VOLUME_MUTE\npublic static final int KEY_GESTURE_TYPE_ALL_APPS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_SEARCH\npublic static final int KEY_GESTURE_TYPE_LANGUAGE_SWITCH\npublic static final int KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS\npublic static final int KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK\npublic static final int KEY_GESTURE_TYPE_SYSTEM_MUTE\npublic static final int KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION\npublic static final int KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS\npublic static final int KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT\npublic static final int KEY_GESTURE_TYPE_LOCK_SCREEN\npublic static final int KEY_GESTURE_TYPE_OPEN_NOTES\npublic static final int KEY_GESTURE_TYPE_TOGGLE_POWER\npublic static final int KEY_GESTURE_TYPE_SYSTEM_NAVIGATION\npublic static final int KEY_GESTURE_TYPE_SLEEP\npublic static final int KEY_GESTURE_TYPE_WAKEUP\npublic static final int KEY_GESTURE_TYPE_MEDIA_KEY\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER\npublic static final int KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS\npublic static final int KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME\npublic static final int KEY_GESTURE_TYPE_DESKTOP_MODE\npublic static final int KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION\nclass KeyGestureEvent extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") + @Deprecated + private void __metadata() {} + + + //@formatter:on + // End of generated code + +} diff --git a/core/java/android/hardware/input/KeyboardSystemShortcut.java b/core/java/android/hardware/input/KeyboardSystemShortcut.java deleted file mode 100644 index 89cf877c3aa8..000000000000 --- a/core/java/android/hardware/input/KeyboardSystemShortcut.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.input; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; - -import com.android.internal.util.DataClass; -import com.android.internal.util.FrameworkStatsLog; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Provides information about the keyboard shortcut being triggered by an external keyboard. - * - * @hide - */ -@DataClass(genToString = true, genEqualsHashCode = true) -public class KeyboardSystemShortcut { - - private static final String TAG = "KeyboardSystemShortcut"; - - @NonNull - private final int[] mKeycodes; - private final int mModifierState; - @SystemShortcut - private final int mSystemShortcut; - - - public static final int SYSTEM_SHORTCUT_UNSPECIFIED = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED; - public static final int SYSTEM_SHORTCUT_HOME = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__HOME; - public static final int SYSTEM_SHORTCUT_RECENT_APPS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RECENT_APPS; - public static final int SYSTEM_SHORTCUT_BACK = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BACK; - public static final int SYSTEM_SHORTCUT_APP_SWITCH = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__APP_SWITCH; - public static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_ASSISTANT; - public static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_VOICE_ASSISTANT; - public static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SYSTEM_SETTINGS; - public static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_NOTIFICATION_PANEL; - public static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_TASKBAR; - public static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TAKE_SCREENSHOT; - public static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_SHORTCUT_HELPER; - public static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_UP; - public static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__BRIGHTNESS_DOWN; - public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_UP; - public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_DOWN; - public static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__KEYBOARD_BACKLIGHT_TOGGLE; - public static final int SYSTEM_SHORTCUT_VOLUME_UP = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_UP; - public static final int SYSTEM_SHORTCUT_VOLUME_DOWN = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_DOWN; - public static final int SYSTEM_SHORTCUT_VOLUME_MUTE = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__VOLUME_MUTE; - public static final int SYSTEM_SHORTCUT_ALL_APPS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ALL_APPS; - public static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_SEARCH; - public static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LANGUAGE_SWITCH; - public static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__ACCESSIBILITY_ALL_APPS; - public static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_CAPS_LOCK; - public static final int SYSTEM_SHORTCUT_SYSTEM_MUTE = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_MUTE; - public static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SPLIT_SCREEN_NAVIGATION; - public static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS; - public static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT; - public static final int SYSTEM_SHORTCUT_LOCK_SCREEN = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LOCK_SCREEN; - public static final int SYSTEM_SHORTCUT_OPEN_NOTES = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__OPEN_NOTES; - public static final int SYSTEM_SHORTCUT_TOGGLE_POWER = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TOGGLE_POWER; - public static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SYSTEM_NAVIGATION; - public static final int SYSTEM_SHORTCUT_SLEEP = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SLEEP; - public static final int SYSTEM_SHORTCUT_WAKEUP = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__WAKEUP; - public static final int SYSTEM_SHORTCUT_MEDIA_KEY = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MEDIA_KEY; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_BROWSER; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_EMAIL; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CONTACTS; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALENDAR; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_CALCULATOR; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MUSIC; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MAPS; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_MESSAGING; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_GALLERY; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FILES; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_WEATHER; - public static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_DEFAULT_FITNESS; - public static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__LAUNCH_APPLICATION_BY_PACKAGE_NAME; - public static final int SYSTEM_SHORTCUT_DESKTOP_MODE = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE; - public static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION = - FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION; - - - - // Code below generated by codegen v1.0.23. - // - // DO NOT MODIFY! - // CHECKSTYLE:OFF Generated code - // - // To regenerate run: - // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java - // - // To exclude the generated code from IntelliJ auto-formatting enable (one-time): - // Settings > Editor > Code Style > Formatter Control - //@formatter:off - - - @IntDef(prefix = "SYSTEM_SHORTCUT_", value = { - SYSTEM_SHORTCUT_UNSPECIFIED, - SYSTEM_SHORTCUT_HOME, - SYSTEM_SHORTCUT_RECENT_APPS, - SYSTEM_SHORTCUT_BACK, - SYSTEM_SHORTCUT_APP_SWITCH, - SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, - SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT, - SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS, - SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, - SYSTEM_SHORTCUT_TOGGLE_TASKBAR, - SYSTEM_SHORTCUT_TAKE_SCREENSHOT, - SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER, - SYSTEM_SHORTCUT_BRIGHTNESS_UP, - SYSTEM_SHORTCUT_BRIGHTNESS_DOWN, - SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP, - SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN, - SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE, - SYSTEM_SHORTCUT_VOLUME_UP, - SYSTEM_SHORTCUT_VOLUME_DOWN, - SYSTEM_SHORTCUT_VOLUME_MUTE, - SYSTEM_SHORTCUT_ALL_APPS, - SYSTEM_SHORTCUT_LAUNCH_SEARCH, - SYSTEM_SHORTCUT_LANGUAGE_SWITCH, - SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, - SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, - SYSTEM_SHORTCUT_SYSTEM_MUTE, - SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION, - SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS, - SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT, - SYSTEM_SHORTCUT_LOCK_SCREEN, - SYSTEM_SHORTCUT_OPEN_NOTES, - SYSTEM_SHORTCUT_TOGGLE_POWER, - SYSTEM_SHORTCUT_SYSTEM_NAVIGATION, - SYSTEM_SHORTCUT_SLEEP, - SYSTEM_SHORTCUT_WAKEUP, - SYSTEM_SHORTCUT_MEDIA_KEY, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER, - SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS, - SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME, - SYSTEM_SHORTCUT_DESKTOP_MODE, - SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION - }) - @Retention(RetentionPolicy.SOURCE) - @DataClass.Generated.Member - public @interface SystemShortcut {} - - @DataClass.Generated.Member - public static String systemShortcutToString(@SystemShortcut int value) { - switch (value) { - case SYSTEM_SHORTCUT_UNSPECIFIED: - return "SYSTEM_SHORTCUT_UNSPECIFIED"; - case SYSTEM_SHORTCUT_HOME: - return "SYSTEM_SHORTCUT_HOME"; - case SYSTEM_SHORTCUT_RECENT_APPS: - return "SYSTEM_SHORTCUT_RECENT_APPS"; - case SYSTEM_SHORTCUT_BACK: - return "SYSTEM_SHORTCUT_BACK"; - case SYSTEM_SHORTCUT_APP_SWITCH: - return "SYSTEM_SHORTCUT_APP_SWITCH"; - case SYSTEM_SHORTCUT_LAUNCH_ASSISTANT: - return "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT"; - case SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT: - return "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT"; - case SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS: - return "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS"; - case SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL: - return "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL"; - case SYSTEM_SHORTCUT_TOGGLE_TASKBAR: - return "SYSTEM_SHORTCUT_TOGGLE_TASKBAR"; - case SYSTEM_SHORTCUT_TAKE_SCREENSHOT: - return "SYSTEM_SHORTCUT_TAKE_SCREENSHOT"; - case SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER: - return "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER"; - case SYSTEM_SHORTCUT_BRIGHTNESS_UP: - return "SYSTEM_SHORTCUT_BRIGHTNESS_UP"; - case SYSTEM_SHORTCUT_BRIGHTNESS_DOWN: - return "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN"; - case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP: - return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP"; - case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN: - return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN"; - case SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE: - return "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE"; - case SYSTEM_SHORTCUT_VOLUME_UP: - return "SYSTEM_SHORTCUT_VOLUME_UP"; - case SYSTEM_SHORTCUT_VOLUME_DOWN: - return "SYSTEM_SHORTCUT_VOLUME_DOWN"; - case SYSTEM_SHORTCUT_VOLUME_MUTE: - return "SYSTEM_SHORTCUT_VOLUME_MUTE"; - case SYSTEM_SHORTCUT_ALL_APPS: - return "SYSTEM_SHORTCUT_ALL_APPS"; - case SYSTEM_SHORTCUT_LAUNCH_SEARCH: - return "SYSTEM_SHORTCUT_LAUNCH_SEARCH"; - case SYSTEM_SHORTCUT_LANGUAGE_SWITCH: - return "SYSTEM_SHORTCUT_LANGUAGE_SWITCH"; - case SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS: - return "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS"; - case SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK: - return "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK"; - case SYSTEM_SHORTCUT_SYSTEM_MUTE: - return "SYSTEM_SHORTCUT_SYSTEM_MUTE"; - case SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION: - return "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION"; - case SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS: - return "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS"; - case SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT: - return "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT"; - case SYSTEM_SHORTCUT_LOCK_SCREEN: - return "SYSTEM_SHORTCUT_LOCK_SCREEN"; - case SYSTEM_SHORTCUT_OPEN_NOTES: - return "SYSTEM_SHORTCUT_OPEN_NOTES"; - case SYSTEM_SHORTCUT_TOGGLE_POWER: - return "SYSTEM_SHORTCUT_TOGGLE_POWER"; - case SYSTEM_SHORTCUT_SYSTEM_NAVIGATION: - return "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION"; - case SYSTEM_SHORTCUT_SLEEP: - return "SYSTEM_SHORTCUT_SLEEP"; - case SYSTEM_SHORTCUT_WAKEUP: - return "SYSTEM_SHORTCUT_WAKEUP"; - case SYSTEM_SHORTCUT_MEDIA_KEY: - return "SYSTEM_SHORTCUT_MEDIA_KEY"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER"; - case SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS: - return "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS"; - case SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME: - return "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME"; - case SYSTEM_SHORTCUT_DESKTOP_MODE: - return "SYSTEM_SHORTCUT_DESKTOP_MODE"; - case SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION: - return "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION"; - default: return Integer.toHexString(value); - } - } - - @DataClass.Generated.Member - public KeyboardSystemShortcut( - @NonNull int[] keycodes, - int modifierState, - @SystemShortcut int systemShortcut) { - this.mKeycodes = keycodes; - com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mKeycodes); - this.mModifierState = modifierState; - this.mSystemShortcut = systemShortcut; - - if (!(mSystemShortcut == SYSTEM_SHORTCUT_UNSPECIFIED) - && !(mSystemShortcut == SYSTEM_SHORTCUT_HOME) - && !(mSystemShortcut == SYSTEM_SHORTCUT_RECENT_APPS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_BACK) - && !(mSystemShortcut == SYSTEM_SHORTCUT_APP_SWITCH) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_ASSISTANT) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_TASKBAR) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TAKE_SCREENSHOT) - && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER) - && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_UP) - && !(mSystemShortcut == SYSTEM_SHORTCUT_BRIGHTNESS_DOWN) - && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP) - && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN) - && !(mSystemShortcut == SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE) - && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_UP) - && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_DOWN) - && !(mSystemShortcut == SYSTEM_SHORTCUT_VOLUME_MUTE) - && !(mSystemShortcut == SYSTEM_SHORTCUT_ALL_APPS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_SEARCH) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LANGUAGE_SWITCH) - && !(mSystemShortcut == SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK) - && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_MUTE) - && !(mSystemShortcut == SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION) - && !(mSystemShortcut == SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LOCK_SCREEN) - && !(mSystemShortcut == SYSTEM_SHORTCUT_OPEN_NOTES) - && !(mSystemShortcut == SYSTEM_SHORTCUT_TOGGLE_POWER) - && !(mSystemShortcut == SYSTEM_SHORTCUT_SYSTEM_NAVIGATION) - && !(mSystemShortcut == SYSTEM_SHORTCUT_SLEEP) - && !(mSystemShortcut == SYSTEM_SHORTCUT_WAKEUP) - && !(mSystemShortcut == SYSTEM_SHORTCUT_MEDIA_KEY) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS) - && !(mSystemShortcut == SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME) - && !(mSystemShortcut == SYSTEM_SHORTCUT_DESKTOP_MODE) - && !(mSystemShortcut == SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION)) { - throw new java.lang.IllegalArgumentException( - "systemShortcut was " + mSystemShortcut + " but must be one of: " - + "SYSTEM_SHORTCUT_UNSPECIFIED(" + SYSTEM_SHORTCUT_UNSPECIFIED + "), " - + "SYSTEM_SHORTCUT_HOME(" + SYSTEM_SHORTCUT_HOME + "), " - + "SYSTEM_SHORTCUT_RECENT_APPS(" + SYSTEM_SHORTCUT_RECENT_APPS + "), " - + "SYSTEM_SHORTCUT_BACK(" + SYSTEM_SHORTCUT_BACK + "), " - + "SYSTEM_SHORTCUT_APP_SWITCH(" + SYSTEM_SHORTCUT_APP_SWITCH + "), " - + "SYSTEM_SHORTCUT_LAUNCH_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_ASSISTANT + "), " - + "SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT(" + SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT + "), " - + "SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS(" + SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS + "), " - + "SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL(" + SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL + "), " - + "SYSTEM_SHORTCUT_TOGGLE_TASKBAR(" + SYSTEM_SHORTCUT_TOGGLE_TASKBAR + "), " - + "SYSTEM_SHORTCUT_TAKE_SCREENSHOT(" + SYSTEM_SHORTCUT_TAKE_SCREENSHOT + "), " - + "SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER(" + SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER + "), " - + "SYSTEM_SHORTCUT_BRIGHTNESS_UP(" + SYSTEM_SHORTCUT_BRIGHTNESS_UP + "), " - + "SYSTEM_SHORTCUT_BRIGHTNESS_DOWN(" + SYSTEM_SHORTCUT_BRIGHTNESS_DOWN + "), " - + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP + "), " - + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN + "), " - + "SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE(" + SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE + "), " - + "SYSTEM_SHORTCUT_VOLUME_UP(" + SYSTEM_SHORTCUT_VOLUME_UP + "), " - + "SYSTEM_SHORTCUT_VOLUME_DOWN(" + SYSTEM_SHORTCUT_VOLUME_DOWN + "), " - + "SYSTEM_SHORTCUT_VOLUME_MUTE(" + SYSTEM_SHORTCUT_VOLUME_MUTE + "), " - + "SYSTEM_SHORTCUT_ALL_APPS(" + SYSTEM_SHORTCUT_ALL_APPS + "), " - + "SYSTEM_SHORTCUT_LAUNCH_SEARCH(" + SYSTEM_SHORTCUT_LAUNCH_SEARCH + "), " - + "SYSTEM_SHORTCUT_LANGUAGE_SWITCH(" + SYSTEM_SHORTCUT_LANGUAGE_SWITCH + "), " - + "SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS(" + SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS + "), " - + "SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK(" + SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK + "), " - + "SYSTEM_SHORTCUT_SYSTEM_MUTE(" + SYSTEM_SHORTCUT_SYSTEM_MUTE + "), " - + "SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION(" + SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION + "), " - + "SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS(" + SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS + "), " - + "SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT(" + SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT + "), " - + "SYSTEM_SHORTCUT_LOCK_SCREEN(" + SYSTEM_SHORTCUT_LOCK_SCREEN + "), " - + "SYSTEM_SHORTCUT_OPEN_NOTES(" + SYSTEM_SHORTCUT_OPEN_NOTES + "), " - + "SYSTEM_SHORTCUT_TOGGLE_POWER(" + SYSTEM_SHORTCUT_TOGGLE_POWER + "), " - + "SYSTEM_SHORTCUT_SYSTEM_NAVIGATION(" + SYSTEM_SHORTCUT_SYSTEM_NAVIGATION + "), " - + "SYSTEM_SHORTCUT_SLEEP(" + SYSTEM_SHORTCUT_SLEEP + "), " - + "SYSTEM_SHORTCUT_WAKEUP(" + SYSTEM_SHORTCUT_WAKEUP + "), " - + "SYSTEM_SHORTCUT_MEDIA_KEY(" + SYSTEM_SHORTCUT_MEDIA_KEY + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER + "), " - + "SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS(" + SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS + "), " - + "SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME(" + SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME + "), " - + "SYSTEM_SHORTCUT_DESKTOP_MODE(" + SYSTEM_SHORTCUT_DESKTOP_MODE + "), " - + "SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION(" + SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION + ")"); - } - - - // onConstructed(); // You can define this method to get a callback - } - - @DataClass.Generated.Member - public @NonNull int[] getKeycodes() { - return mKeycodes; - } - - @DataClass.Generated.Member - public int getModifierState() { - return mModifierState; - } - - @DataClass.Generated.Member - public @SystemShortcut int getSystemShortcut() { - return mSystemShortcut; - } - - @Override - @DataClass.Generated.Member - public String toString() { - // You can override field toString logic by defining methods like: - // String fieldNameToString() { ... } - - return "KeyboardSystemShortcut { " + - "keycodes = " + java.util.Arrays.toString(mKeycodes) + ", " + - "modifierState = " + mModifierState + ", " + - "systemShortcut = " + systemShortcutToString(mSystemShortcut) + - " }"; - } - - @Override - @DataClass.Generated.Member - public boolean equals(@Nullable Object o) { - // You can override field equality logic by defining either of the methods like: - // boolean fieldNameEquals(KeyboardSystemShortcut other) { ... } - // boolean fieldNameEquals(FieldType otherValue) { ... } - - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - @SuppressWarnings("unchecked") - KeyboardSystemShortcut that = (KeyboardSystemShortcut) o; - //noinspection PointlessBooleanExpression - return true - && java.util.Arrays.equals(mKeycodes, that.mKeycodes) - && mModifierState == that.mModifierState - && mSystemShortcut == that.mSystemShortcut; - } - - @Override - @DataClass.Generated.Member - public int hashCode() { - // You can override field hashCode logic by defining methods like: - // int fieldNameHashCode() { ... } - - int _hash = 1; - _hash = 31 * _hash + java.util.Arrays.hashCode(mKeycodes); - _hash = 31 * _hash + mModifierState; - _hash = 31 * _hash + mSystemShortcut; - return _hash; - } - - @DataClass.Generated( - time = 1722890917041L, - codegenVersion = "1.0.23", - sourceFile = "frameworks/base/core/java/android/hardware/input/KeyboardSystemShortcut.java", - inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull int[] mKeycodes\nprivate final int mModifierState\nprivate final @android.hardware.input.KeyboardSystemShortcut.SystemShortcut int mSystemShortcut\npublic static final int SYSTEM_SHORTCUT_UNSPECIFIED\npublic static final int SYSTEM_SHORTCUT_HOME\npublic static final int SYSTEM_SHORTCUT_RECENT_APPS\npublic static final int SYSTEM_SHORTCUT_BACK\npublic static final int SYSTEM_SHORTCUT_APP_SWITCH\npublic static final int SYSTEM_SHORTCUT_LAUNCH_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL\npublic static final int SYSTEM_SHORTCUT_TOGGLE_TASKBAR\npublic static final int SYSTEM_SHORTCUT_TAKE_SCREENSHOT\npublic static final int SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_UP\npublic static final int SYSTEM_SHORTCUT_BRIGHTNESS_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN\npublic static final int SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE\npublic static final int SYSTEM_SHORTCUT_VOLUME_UP\npublic static final int SYSTEM_SHORTCUT_VOLUME_DOWN\npublic static final int SYSTEM_SHORTCUT_VOLUME_MUTE\npublic static final int SYSTEM_SHORTCUT_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_SEARCH\npublic static final int SYSTEM_SHORTCUT_LANGUAGE_SWITCH\npublic static final int SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS\npublic static final int SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK\npublic static final int SYSTEM_SHORTCUT_SYSTEM_MUTE\npublic static final int SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS\npublic static final int SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT\npublic static final int SYSTEM_SHORTCUT_LOCK_SCREEN\npublic static final int SYSTEM_SHORTCUT_OPEN_NOTES\npublic static final int SYSTEM_SHORTCUT_TOGGLE_POWER\npublic static final int SYSTEM_SHORTCUT_SYSTEM_NAVIGATION\npublic static final int SYSTEM_SHORTCUT_SLEEP\npublic static final int SYSTEM_SHORTCUT_WAKEUP\npublic static final int SYSTEM_SHORTCUT_MEDIA_KEY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER\npublic static final int SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS\npublic static final int SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME\npublic static final int SYSTEM_SHORTCUT_DESKTOP_MODE\npublic static final int SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION\nclass KeyboardSystemShortcut extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)") - @Deprecated - private void __metadata() {} - - - //@formatter:on - // End of generated code - -} diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 1fb7937ff847..29ccb85c0bab 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -145,10 +145,11 @@ public abstract class PowerManagerInternal { * @param screenBrightnessInt The overridden screen brightness between 1 and 255, or * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. Not used if * screenBrightnessFloat is provided (is not NaN). + * @param useNormalBrightnessForDoze Whether use normal brightness while device is dozing. */ public abstract void setDozeOverrideFromDreamManager( int screenState, @Display.StateReason int reason, float screenBrightnessFloat, - int screenBrightnessInt); + int screenBrightnessInt, boolean useNormalBrightnessForDoze); /** * Used by sidekick manager to tell the power manager if it shouldn't change the display state diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java index da863e58a882..589622710f3e 100644 --- a/core/java/android/os/VibrationAttributes.java +++ b/core/java/android/os/VibrationAttributes.java @@ -151,31 +151,6 @@ public final class VibrationAttributes implements Parcelable { */ public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA; - /** @hide */ - @IntDef(prefix = { "CATEGORY_" }, value = { - CATEGORY_UNKNOWN, - CATEGORY_KEYBOARD, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface Category {} - - /** - * Category value when the vibration category is unknown. - * - * @hide - */ - public static final int CATEGORY_UNKNOWN = 0x0; - - /** - * Category value for keyboard vibrations. - * - * <p>Most typical keyboard vibrations are haptic feedback for virtual keyboard key - * press/release, for example. - * - * @hide - */ - public static final int CATEGORY_KEYBOARD = 1; - /** * @hide */ @@ -252,14 +227,12 @@ public final class VibrationAttributes implements Parcelable { private final int mUsage; private final int mFlags; private final int mOriginalAudioUsage; - private final int mCategory; private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage, - @Flag int flags, @Category int category) { + @Flag int flags) { mUsage = usage; mOriginalAudioUsage = audioUsage; mFlags = flags & FLAG_ALL_SUPPORTED; - mCategory = category; } /** @@ -297,20 +270,6 @@ public final class VibrationAttributes implements Parcelable { } /** - * Return the vibration category. - * - * <p>Vibration categories describe the source of the vibration, and it can be combined with - * the vibration usage to best match to a user setting, e.g. a vibration with usage touch and - * category keyboard can be used to control keyboard haptic feedback independently. - * - * @hide - */ - @Category - public int getCategory() { - return mCategory; - } - - /** * Check whether a flag is set * @return true if a flag is set and false otherwise */ @@ -362,14 +321,12 @@ public final class VibrationAttributes implements Parcelable { dest.writeInt(mUsage); dest.writeInt(mOriginalAudioUsage); dest.writeInt(mFlags); - dest.writeInt(mCategory); } private VibrationAttributes(Parcel src) { mUsage = src.readInt(); mOriginalAudioUsage = src.readInt(); mFlags = src.readInt(); - mCategory = src.readInt(); } public static final @NonNull Parcelable.Creator<VibrationAttributes> @@ -392,12 +349,12 @@ public final class VibrationAttributes implements Parcelable { } VibrationAttributes rhs = (VibrationAttributes) o; return mUsage == rhs.mUsage && mOriginalAudioUsage == rhs.mOriginalAudioUsage - && mFlags == rhs.mFlags && mCategory == rhs.mCategory; + && mFlags == rhs.mFlags; } @Override public int hashCode() { - return Objects.hash(mUsage, mOriginalAudioUsage, mFlags, mCategory); + return Objects.hash(mUsage, mOriginalAudioUsage, mFlags); } @Override @@ -405,7 +362,6 @@ public final class VibrationAttributes implements Parcelable { return "VibrationAttributes{" + "mUsage=" + usageToString() + ", mAudioUsage= " + AudioAttributes.usageToString(mOriginalAudioUsage) - + ", mCategory=" + categoryToString() + ", mFlags=" + mFlags + '}'; } @@ -445,23 +401,6 @@ public final class VibrationAttributes implements Parcelable { } } - /** @hide */ - public String categoryToString() { - return categoryToString(mCategory); - } - - /** @hide */ - public static String categoryToString(@Category int category) { - switch (category) { - case CATEGORY_UNKNOWN: - return "UNKNOWN"; - case CATEGORY_KEYBOARD: - return "KEYBOARD"; - default: - return "unknown category " + category; - } - } - /** * Builder class for {@link VibrationAttributes} objects. * By default, all information is set to UNKNOWN. @@ -471,7 +410,6 @@ public final class VibrationAttributes implements Parcelable { private int mUsage = USAGE_UNKNOWN; private int mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN; private int mFlags = 0x0; - private int mCategory = CATEGORY_UNKNOWN; /** * Constructs a new Builder with the defaults. @@ -487,7 +425,6 @@ public final class VibrationAttributes implements Parcelable { mUsage = vib.mUsage; mOriginalAudioUsage = vib.mOriginalAudioUsage; mFlags = vib.mFlags; - mCategory = vib.mCategory; } } @@ -554,7 +491,7 @@ public final class VibrationAttributes implements Parcelable { */ public @NonNull VibrationAttributes build() { VibrationAttributes ans = new VibrationAttributes( - mUsage, mOriginalAudioUsage, mFlags, mCategory); + mUsage, mOriginalAudioUsage, mFlags); return ans; } @@ -570,19 +507,6 @@ public final class VibrationAttributes implements Parcelable { } /** - * Sets the attribute describing the category of the corresponding vibration. - * - * @param category The category for the vibration - * @return the same Builder instance. - * - * @hide - */ - public @NonNull Builder setCategory(@Category int category) { - mCategory = category; - return this; - } - - /** * Sets only the flags specified in the bitmask, leaving the other supported flag values * unchanged in the builder. * diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index e68b74683292..f02d4a9ce4a7 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -346,7 +346,7 @@ public abstract class VibrationEffect implements Parcelable { @RequiresPermission(android.Manifest.permission.VIBRATE_VENDOR_EFFECTS) public static VibrationEffect createVendorEffect(@NonNull PersistableBundle effect) { VibrationEffect vendorEffect = new VendorEffect(effect, VendorEffect.DEFAULT_STRENGTH, - VendorEffect.DEFAULT_SCALE); + VendorEffect.DEFAULT_SCALE, VendorEffect.DEFAULT_SCALE); vendorEffect.validate(); return vendorEffect; } @@ -623,7 +623,7 @@ public abstract class VibrationEffect implements Parcelable { * @hide */ @NonNull - public abstract VibrationEffect scaleLinearly(float scaleFactor); + public abstract VibrationEffect applyAdaptiveScale(float scaleFactor); /** * Ensures that the effect is repeating indefinitely or not. This is a lossy operation and @@ -948,7 +948,7 @@ public abstract class VibrationEffect implements Parcelable { /** @hide */ @NonNull @Override - public Composed scaleLinearly(float scaleFactor) { + public Composed applyAdaptiveScale(float scaleFactor) { return applyToSegments(VibrationEffectSegment::scaleLinearly, scaleFactor); } @@ -1100,21 +1100,23 @@ public abstract class VibrationEffect implements Parcelable { private final PersistableBundle mVendorData; private final int mEffectStrength; - private final float mLinearScale; + private final float mScale; + private final float mAdaptiveScale; /** @hide */ VendorEffect(@NonNull Parcel in) { this(Objects.requireNonNull( in.readPersistableBundle(VibrationEffect.class.getClassLoader())), - in.readInt(), in.readFloat()); + in.readInt(), in.readFloat(), in.readFloat()); } /** @hide */ public VendorEffect(@NonNull PersistableBundle vendorData, int effectStrength, - float linearScale) { + float scale, float adaptiveScale) { mVendorData = vendorData; mEffectStrength = effectStrength; - mLinearScale = linearScale; + mScale = scale; + mAdaptiveScale = adaptiveScale; } @NonNull @@ -1126,8 +1128,12 @@ public abstract class VibrationEffect implements Parcelable { return mEffectStrength; } - public float getLinearScale() { - return mLinearScale; + public float getScale() { + return mScale; + } + + public float getAdaptiveScale() { + return mAdaptiveScale; } /** @hide */ @@ -1175,7 +1181,8 @@ public abstract class VibrationEffect implements Parcelable { if (mEffectStrength == effectStrength) { return this; } - VendorEffect updated = new VendorEffect(mVendorData, effectStrength, mLinearScale); + VendorEffect updated = new VendorEffect(mVendorData, effectStrength, mScale, + mAdaptiveScale); updated.validate(); return updated; } @@ -1184,18 +1191,24 @@ public abstract class VibrationEffect implements Parcelable { @NonNull @Override public VendorEffect scale(float scaleFactor) { - // Vendor effect strength cannot be scaled with this method. - return this; + if (Float.compare(mScale, scaleFactor) == 0) { + return this; + } + VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, scaleFactor, + mAdaptiveScale); + updated.validate(); + return updated; } /** @hide */ @NonNull @Override - public VibrationEffect scaleLinearly(float scaleFactor) { - if (Float.compare(mLinearScale, scaleFactor) == 0) { + public VibrationEffect applyAdaptiveScale(float scaleFactor) { + if (Float.compare(mAdaptiveScale, scaleFactor) == 0) { return this; } - VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, scaleFactor); + VendorEffect updated = new VendorEffect(mVendorData, mEffectStrength, mScale, + scaleFactor); updated.validate(); return updated; } @@ -1216,29 +1229,31 @@ public abstract class VibrationEffect implements Parcelable { return false; } return mEffectStrength == other.mEffectStrength - && (Float.compare(mLinearScale, other.mLinearScale) == 0) + && (Float.compare(mScale, other.mScale) == 0) + && (Float.compare(mAdaptiveScale, other.mAdaptiveScale) == 0) && isPersistableBundleEquals(mVendorData, other.mVendorData); } @Override public int hashCode() { // PersistableBundle does not implement hashCode, so use its size as a shortcut. - return Objects.hash(mVendorData.size(), mEffectStrength, mLinearScale); + return Objects.hash(mVendorData.size(), mEffectStrength, mScale, mAdaptiveScale); } @Override public String toString() { return String.format(Locale.ROOT, - "VendorEffect{vendorData=%s, strength=%s, scale=%.2f}", - mVendorData, effectStrengthToString(mEffectStrength), mLinearScale); + "VendorEffect{vendorData=%s, strength=%s, scale=%.2f, adaptiveScale=%.2f}", + mVendorData, effectStrengthToString(mEffectStrength), mScale, mAdaptiveScale); } /** @hide */ @Override public String toDebugString() { - return String.format(Locale.ROOT, "vendorEffect=%s, strength=%s, scale=%.2f", + return String.format(Locale.ROOT, + "vendorEffect=%s, strength=%s, scale=%.2f, adaptiveScale=%.2f", mVendorData.toShortString(), effectStrengthToString(mEffectStrength), - mLinearScale); + mScale, mAdaptiveScale); } @Override @@ -1251,7 +1266,8 @@ public abstract class VibrationEffect implements Parcelable { out.writeInt(PARCEL_TOKEN_VENDOR_EFFECT); out.writePersistableBundle(mVendorData); out.writeInt(mEffectStrength); - out.writeFloat(mLinearScale); + out.writeFloat(mScale); + out.writeFloat(mAdaptiveScale); } /** diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig index 53a1a67dfc58..e3b1221b3004 100644 --- a/core/java/android/os/vibrator/flags.aconfig +++ b/core/java/android/os/vibrator/flags.aconfig @@ -113,3 +113,14 @@ flag { purpose: PURPOSE_FEATURE } } + +flag { + namespace: "haptics" + name: "normalized_pwle_effects" + is_exported: true + description: "Enables functionality to create PWLE effects using advanced and simple APIs" + bug: "341052318" + metadata { + purpose: PURPOSE_FEATURE + } +}
\ No newline at end of file diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index 3fe063df0e1b..5174005a8175 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -217,9 +217,27 @@ flag { } flag { + name: "check_op_validate_package" + namespace: "permissions" + description: "Validate package/uid match in checkOp similar to noteOp" + bug: "294609684" +} + +flag { name: "location_bypass_privacy_dashboard_enabled" is_exported: true namespace: "permissions" description: "Show access entry of location bypass permission in the Privacy Dashboard" bug: "325536053" } + +flag { + name: "dont_remove_existing_uid_states" + is_fixed_read_only: true + namespace: "permissions" + description: "Double check if the uid still exists before attempting to remove its appops state" + bug: "353474742" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7ca40ea23d57..184bac4269bb 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14953,6 +14953,7 @@ public final class Settings { * * @hide */ + @Readable public static final String MUTE_ALARM_STREAM_WITH_RINGER_MODE = "mute_alarm_stream_with_ringer_mode"; diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 133b3d1add49..0242de0b972c 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -17,8 +17,8 @@ package android.service.dreams; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.service.dreams.Flags.dreamHandlesConfirmKeys; import static android.service.dreams.Flags.dreamHandlesBeingObscured; +import static android.service.dreams.Flags.dreamHandlesConfirmKeys; import static android.service.dreams.Flags.startAndStopDozingInBackground; import android.annotation.FlaggedApi; @@ -272,6 +272,9 @@ public class DreamService extends Service implements Window.Callback { private int mDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; private float mDozeScreenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; + // This variable being true means dozing device expecting normal(non-doze) brightness. + private boolean mUseNormalBrightnessForDoze; + private boolean mDebug = false; private ComponentName mDreamComponent; @@ -935,13 +938,14 @@ public class DreamService extends Service implements Window.Callback { if (startAndStopDozingInBackground()) { mDreamManager.startDozingOneway( mDreamToken, mDozeScreenState, mDozeScreenStateReason, - mDozeScreenBrightnessFloat, mDozeScreenBrightness); + mDozeScreenBrightnessFloat, mDozeScreenBrightness, + mUseNormalBrightnessForDoze); } else { mDreamManager.startDozing( mDreamToken, mDozeScreenState, mDozeScreenStateReason, - mDozeScreenBrightnessFloat, mDozeScreenBrightness); + mDozeScreenBrightnessFloat, mDozeScreenBrightness, + mUseNormalBrightnessForDoze); } - } catch (RemoteException ex) { // system server died } @@ -1010,7 +1014,8 @@ public class DreamService extends Service implements Window.Callback { */ @UnsupportedAppUsage public void setDozeScreenState(int state) { - setDozeScreenState(state, Display.STATE_REASON_UNKNOWN); + setDozeScreenState(state, Display.STATE_REASON_UNKNOWN, + /* useNormalBrightnessForDoze= */ false); } /** @@ -1048,21 +1053,43 @@ public class DreamService extends Service implements Window.Callback { * {@link Display#STATE_ON_SUSPEND}, {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} * for the default behavior. * @param reason the reason for setting the specified screen state. - * - * @hide For use by system UI components only. + * @param useNormalBrightnessForDoze False means the default case where doze brightness is + * expected when device is dozing. True means display expects normal brightness for next doze + * request. Noted: unlike {@link #setDozeScreenBrightness} that sets a real brightness value for + * doze screen, this parameter only indicates whether the doze brightness is intended on next + * doze screen. The actual brightness value will be computed by {@link DisplayManager} + * internally. + * @hide For use by System UI components only. */ @UnsupportedAppUsage - public void setDozeScreenState(int state, @Display.StateReason int reason) { + public void setDozeScreenState(int state, @Display.StateReason int reason, + boolean useNormalBrightnessForDoze) { synchronized (this) { - if (mDozeScreenState != state) { + if (mDozeScreenState != state + || mUseNormalBrightnessForDoze != useNormalBrightnessForDoze) { mDozeScreenState = state; mDozeScreenStateReason = reason; + mUseNormalBrightnessForDoze = useNormalBrightnessForDoze; updateDoze(); } } } /** + * Returns whether we want to use the normal brightness setting while in doze. This is useful + * on devices like Wear; when we allow the user to interact with a device that remains in + * doze (looking at time). + * + * @return a boolean that informs {@link DisplayManager} whether to adjust the display for the + * interacting user e.g. brightening the display. + * @hide For use by System UI components only. + */ + @UnsupportedAppUsage + public boolean getUseNormalBrightnessForDoze() { + return mUseNormalBrightnessForDoze; + } + + /** * Gets the screen brightness to use while dozing. * * @return The screen brightness while dozing as a value between @@ -1336,6 +1363,9 @@ public class DreamService extends Service implements Window.Callback { * Tells the dream to come to the front (which in turn tells the overlay to come to the front). */ private void comeToFront() { + if (mOverlayConnection == null) { + return; + } mOverlayConnection.addConsumer(overlay -> { try { overlay.comeToFront(); diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 611e7912517b..1c0a2c021bca 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -43,7 +43,7 @@ interface IDreamManager { void finishSelf(in IBinder token, boolean immediate); /** @deprecated Please use startDozingOneway instead. */ void startDozing(in IBinder token, int screenState, int reason, float screenBrightnessFloat, - int screenBrightnessInt); + int screenBrightnessInt, boolean useNormalBrightnessForDoze); void stopDozing(in IBinder token); void forceAmbientDisplayEnabled(boolean enabled); ComponentName[] getDreamComponentsForUser(int userId); @@ -54,6 +54,7 @@ interface IDreamManager { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)") oneway void setDreamIsObscured(in boolean isObscured); oneway void startDozingOneway(in IBinder token, int screenState, int reason, - float screenBrightnessFloat, int screenBrightnessInt); + float screenBrightnessFloat, int screenBrightnessInt, + boolean useNormalBrightnessForDoze); oneway void finishSelfOneway(in IBinder token, boolean immediate); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 66d08f99516e..1734223ec4c1 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -27,6 +27,7 @@ import static android.view.View.SYSTEM_UI_FLAG_VISIBLE; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION; +import static com.android.window.flags.Flags.noDuplicateSurfaceDestroyedEvents; import static com.android.window.flags.Flags.noConsecutiveVisibilityEvents; import static com.android.window.flags.Flags.noVisibilityEventOnDisplayStateChange; import static com.android.window.flags.Flags.offloadColorExtraction; @@ -255,6 +256,7 @@ public abstract class WallpaperService extends Service { */ private boolean mIsScreenTurningOn; boolean mReportedVisible; + boolean mReportedSurfaceCreated; boolean mDestroyed; // Set to true after receiving WallpaperManager#COMMAND_FREEZE. It's reset back to false // after receiving WallpaperManager#COMMAND_UNFREEZE. COMMAND_FREEZE is fully applied once @@ -1076,6 +1078,9 @@ public abstract class WallpaperService extends Service { out.print(prefix); out.print("mDisplay="); out.println(mDisplay); out.print(prefix); out.print("mCreated="); out.print(mCreated); out.print(" mSurfaceCreated="); out.print(mSurfaceCreated); + if (noDuplicateSurfaceDestroyedEvents()) { + out.print(" mReportedSurfaceCreated="); out.print(mReportedSurfaceCreated); + } out.print(" mIsCreating="); out.print(mIsCreating); out.print(" mDrawingAllowed="); out.println(mDrawingAllowed); out.print(prefix); out.print("mWidth="); out.print(mWidth); @@ -1381,6 +1386,7 @@ public abstract class WallpaperService extends Service { if (surfaceCreating) { mIsCreating = true; didSurface = true; + mReportedSurfaceCreated = true; if (DEBUG) Log.v(TAG, "onSurfaceCreated(" + mSurfaceHolder + "): " + this); Trace.beginSection("WPMS.Engine.onSurfaceCreated"); @@ -2264,8 +2270,10 @@ public abstract class WallpaperService extends Service { } void reportSurfaceDestroyed() { - if (mSurfaceCreated) { + if ((!noDuplicateSurfaceDestroyedEvents() && mSurfaceCreated) + || (noDuplicateSurfaceDestroyedEvents() && mReportedSurfaceCreated)) { mSurfaceCreated = false; + mReportedSurfaceCreated = false; mSurfaceHolder.ungetCallbacks(); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); if (callbacks != null) { diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java index 6a54d2378f6c..711578c1482f 100644 --- a/core/java/android/text/Selection.java +++ b/core/java/android/text/Selection.java @@ -350,7 +350,7 @@ public class Selection { private static final char PARAGRAPH_SEPARATOR = '\n'; /** - * Move the cusrot to the closest paragraph start offset. + * Move the cursor to the closest paragraph start offset. * * @param text the spannable text * @param layout layout to be used for drawing. diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index 3d190fe43626..1c3d73824e7e 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -267,3 +267,23 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "typeface_cache_for_var_settings" + namespace: "text" + description: "Cache Typeface instance for font variation settings." + bug: "355462362" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "context_menu_hide_unavailable_items" + namespace: "text" + description: "Hide rather than disable unavailable Editor context menu items." + bug: "345709107" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 3adbd686cd2c..9f54d9fca24b 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.Network; -import android.net.NetworkInfo; +import android.net.NetworkCapabilities; import android.net.SntpClient; import android.os.Build; import android.os.SystemClock; @@ -687,8 +687,16 @@ public abstract class NtpTrustedTime implements TrustedTime { if (connectivityManager == null) { return false; } - final NetworkInfo ni = connectivityManager.getNetworkInfo(network); - + final NetworkCapabilities networkCapabilities = + connectivityManager.getNetworkCapabilities(network); + if (networkCapabilities == null) { + if (LOGD) Log.d(TAG, "getNetwork: failed to get network capabilities"); + return false; + } + final boolean isConnectedToInternet = networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET) + && networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_VALIDATED); // This connectivity check is to avoid performing a DNS lookup for the time server on a // unconnected network. There are races to obtain time in Android when connectivity // changes, which means that forceRefresh() can be called by various components before @@ -698,8 +706,8 @@ public abstract class NtpTrustedTime implements TrustedTime { // A side effect of check is that tests that run a fake NTP server on the device itself // will only be able to use it if the active network is connected, even though loopback // addresses are actually reachable. - if (ni == null || !ni.isConnected()) { - if (LOGD) Log.d(TAG, "getNetwork: no connectivity"); + if (!isConnectedToInternet) { + if (LOGD) Log.d(TAG, "getNetwork: no internet connectivity"); return false; } return true; diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java index ccec89bb6262..8912035c0be3 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -350,12 +350,13 @@ public class HandwritingInitiator { return; } + final View focusedView = getFocusedView(); + if (!view.isAutoHandwritingEnabled()) { - clearFocusedView(view); + clearFocusedView(focusedView); return; } - final View focusedView = getFocusedView(); if (focusedView == view) { return; } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 42d66ce6bf1b..f7745d14188e 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -325,17 +325,62 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private String mTag = TAG; - private final ISurfaceControlViewHostParent mSurfaceControlViewHostParent = - new ISurfaceControlViewHostParent.Stub() { + private static class SurfaceControlViewHostParent extends ISurfaceControlViewHostParent.Stub { + + /** + * mSurfaceView is set in {@link #attach} and cleared in {@link #detach} to prevent + * temporary memory leaks. The remote process's ISurfaceControlViewHostParent binder + * reference extends this object's lifetime. If mSurfaceView is not cleared in + * {@link #detach}, then the SurfaceView and anything it references will not be promptly + * garbage collected. + */ + @Nullable + private SurfaceView mSurfaceView; + + void attach(SurfaceView sv) { + synchronized (this) { + try { + sv.mSurfacePackage.getRemoteInterface().attachParentInterface(this); + mSurfaceView = sv; + } catch (RemoteException e) { + Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is alraedy " + + "dead."); + } + } + } + + void detach() { + synchronized (this) { + if (mSurfaceView == null) { + return; + } + try { + mSurfaceView.mSurfacePackage.getRemoteInterface().attachParentInterface(null); + } catch (RemoteException e) { + Log.d(TAG, "Failed to remove parent interface from SCVH. Likely SCVH is " + + "already dead"); + } + mSurfaceView = null; + } + } + @Override public void updateParams(WindowManager.LayoutParams[] childAttrs) { - mEmbeddedWindowParams.clear(); - mEmbeddedWindowParams.addAll(Arrays.asList(childAttrs)); + SurfaceView sv; + synchronized (this) { + sv = mSurfaceView; + } + if (sv == null) { + return; + } + + sv.mEmbeddedWindowParams.clear(); + sv.mEmbeddedWindowParams.addAll(Arrays.asList(childAttrs)); - if (isAttachedToWindow()) { - runOnUiThread(() -> { - if (mParent != null) { - mParent.recomputeViewAttributes(SurfaceView.this); + if (sv.isAttachedToWindow()) { + sv.runOnUiThread(() -> { + if (sv.mParent != null) { + sv.mParent.recomputeViewAttributes(sv); } }); } @@ -343,34 +388,45 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void forwardBackKeyToParent(@NonNull KeyEvent keyEvent) { - runOnUiThread(() -> { - if (!isAttachedToWindow() || keyEvent.getKeyCode() != KeyEvent.KEYCODE_BACK) { - return; - } - final ViewRootImpl vri = getViewRootImpl(); - if (vri == null) { - return; - } - final InputManager inputManager = mContext.getSystemService(InputManager.class); - if (inputManager == null) { - return; - } - // Check that the event was created recently. - final long timeDiff = SystemClock.uptimeMillis() - keyEvent.getEventTime(); - if (timeDiff > FORWARD_BACK_KEY_TOLERANCE_MS) { - Log.e(TAG, "Ignore the input event that exceed the tolerance time, " - + "exceed " + timeDiff + "ms"); - return; - } - if (inputManager.verifyInputEvent(keyEvent) == null) { - Log.e(TAG, "Received invalid input event"); - return; - } - vri.enqueueInputEvent(keyEvent, null /* receiver */, 0 /* flags */, - true /* processImmediately */); - }); + SurfaceView sv; + synchronized (this) { + sv = mSurfaceView; + } + if (sv == null) { + return; + } + + sv.runOnUiThread(() -> { + if (!sv.isAttachedToWindow() || keyEvent.getKeyCode() != KeyEvent.KEYCODE_BACK) { + return; + } + final ViewRootImpl vri = sv.getViewRootImpl(); + if (vri == null) { + return; + } + final InputManager inputManager = sv.mContext.getSystemService(InputManager.class); + if (inputManager == null) { + return; + } + // Check that the event was created recently. + final long timeDiff = SystemClock.uptimeMillis() - keyEvent.getEventTime(); + if (timeDiff > FORWARD_BACK_KEY_TOLERANCE_MS) { + Log.e(TAG, "Ignore the input event that exceed the tolerance time, " + + "exceed " + timeDiff + "ms"); + return; + } + if (inputManager.verifyInputEvent(keyEvent) == null) { + Log.e(TAG, "Received invalid input event"); + return; + } + vri.enqueueInputEvent(keyEvent, null /* receiver */, 0 /* flags */, + true /* processImmediately */); + }); } - }; + } + + private final SurfaceControlViewHostParent mSurfaceControlViewHostParent = + new SurfaceControlViewHostParent(); private final boolean mRtDrivenClipping = Flags.clipSurfaceviews(); @@ -930,13 +986,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } if (mSurfacePackage != null) { - try { - mSurfacePackage.getRemoteInterface().attachParentInterface(null); - mEmbeddedWindowParams.clear(); - } catch (RemoteException e) { - Log.d(TAG, "Failed to remove parent interface from SCVH. Likely SCVH is " - + "already dead"); - } + mSurfaceControlViewHostParent.detach(); + mEmbeddedWindowParams.clear(); if (releaseSurfacePackage) { mSurfacePackage.release(); mSurfacePackage = null; @@ -2067,12 +2118,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall applyTransactionOnVriDraw(transaction); } mSurfacePackage = p; - try { - mSurfacePackage.getRemoteInterface().attachParentInterface( - mSurfaceControlViewHostParent); - } catch (RemoteException e) { - Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is already dead."); - } + mSurfaceControlViewHostParent.attach(this); if (isFocused()) { requestEmbeddedFocus(true); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3088fd3094b0..e81f32e1e64b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -33989,7 +33989,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, || mLastFrameTop != mTop) && viewRootImpl.shouldCheckFrameRateCategory() && parent instanceof View - && ((View) parent).mFrameContentVelocity <= 0 + && ((View) parent).getFrameContentVelocity() <= 0 && !isInputMethodWindowType) { return FRAME_RATE_CATEGORY_HIGH_HINT | FRAME_RATE_CATEGORY_REASON_BOOST; diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java index 02f7e95ba742..2786c84521c5 100644 --- a/core/java/android/view/ViewOverlay.java +++ b/core/java/android/view/ViewOverlay.java @@ -15,7 +15,10 @@ */ package android.view; +import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API; + import android.animation.LayoutTransition; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -365,6 +368,18 @@ public class ViewOverlay { } return null; } + + /** + * @hide + */ + @Override + @FlaggedApi(FLAG_VIEW_VELOCITY_API) + public float getFrameContentVelocity() { + if (mHostView != null) { + return mHostView.getFrameContentVelocity(); + } + return super.getFrameContentVelocity(); + } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1c0700f69ab6..0e0262715d2f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -133,6 +133,7 @@ import static com.android.window.flags.Flags.enableCaptionCompatInsetForceConsum import static com.android.window.flags.Flags.insetsControlChangedItem; import static com.android.window.flags.Flags.insetsControlSeq; import static com.android.window.flags.Flags.setScPropertiesInClient; +import static com.android.window.flags.Flags.systemUiImmersiveConfirmationDialog; import android.Manifest; import android.accessibilityservice.AccessibilityService; @@ -303,6 +304,7 @@ import java.util.OptionalInt; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; /** @@ -378,7 +380,7 @@ public final class ViewRootImpl implements ViewParent, * @hide */ public static final boolean CLIENT_IMMERSIVE_CONFIRMATION = - SystemProperties.getBoolean("persist.wm.debug.client_immersive_confirmation", false); + systemUiImmersiveConfirmationDialog(); /** * Set this system property to true to force the view hierarchy to render @@ -1200,8 +1202,7 @@ public final class ViewRootImpl implements ViewParent, private String mLargestViewTraceName; private final boolean mAppStartInfoTimestampsFlagValue; - @GuardedBy("this") - private boolean mAppStartTimestampsSent = false; + private AtomicBoolean mAppStartTimestampsSent = new AtomicBoolean(false); private boolean mAppStartTrackingStarted = false; private long mRenderThreadDrawStartTimeNs = -1; private long mFirstFramePresentedTimeNs = -1; @@ -2646,7 +2647,7 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); // Reset so they can be sent again for warm starts. - mAppStartTimestampsSent = false; + mAppStartTimestampsSent.set(false); mAppStartTrackingStarted = false; mRenderThreadDrawStartTimeNs = -1; mFirstFramePresentedTimeNs = -1; @@ -4502,42 +4503,29 @@ public final class ViewRootImpl implements ViewParent, } private void maybeSendAppStartTimes() { - synchronized (this) { - if (mAppStartTimestampsSent) { - // Don't send timestamps more than once. - return; - } - - // If we already have {@link mRenderThreadDrawStartTimeNs} then pass it through, if not - // post to main thread and check if we have it there. - if (mRenderThreadDrawStartTimeNs != -1) { - sendAppStartTimesLocked(); - } else { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (ViewRootImpl.this) { - if (mRenderThreadDrawStartTimeNs == -1) { - return; - } - sendAppStartTimesLocked(); - } - } - }); - } + if (mAppStartTimestampsSent.get()) { + // Don't send timestamps more than once. + return; } - } - @GuardedBy("this") - private void sendAppStartTimesLocked() { - try { - ActivityManager.getService().reportStartInfoViewTimestamps( - mRenderThreadDrawStartTimeNs, mFirstFramePresentedTimeNs); - mAppStartTimestampsSent = true; - } catch (RemoteException e) { - // Ignore, timestamps may be lost. - if (DBG) Log.d(TAG, "Exception attempting to report start timestamps.", e); - } + // Post to main thread + mHandler.post(new Runnable() { + @Override + public void run() { + if (mRenderThreadDrawStartTimeNs == -1) { + return; + } + + try { + ActivityManager.getService().reportStartInfoViewTimestamps( + mRenderThreadDrawStartTimeNs, mFirstFramePresentedTimeNs); + mAppStartTimestampsSent.set(true); + } catch (RemoteException e) { + // Ignore, timestamps may be lost. + if (DBG) Log.d(TAG, "Exception attempting to report start timestamps.", e); + } + } + }); } /** @@ -13024,7 +13012,7 @@ public final class ViewRootImpl implements ViewParent, private boolean shouldSetFrameRateCategory() { // use toolkitSetFrameRate flag to gate the change - return shouldEnableDvrr() && mSurface.isValid() && shouldEnableDvrr(); + return shouldEnableDvrr() && mSurface.isValid(); } private boolean shouldSetFrameRate() { diff --git a/core/java/android/view/contentprotection/OWNERS b/core/java/android/view/contentprotection/OWNERS index b3583a7f6ab1..48052c640560 100644 --- a/core/java/android/view/contentprotection/OWNERS +++ b/core/java/android/view/contentprotection/OWNERS @@ -1,4 +1,6 @@ -# Bug component: 544200 +# Bug component: 1040349 -include /core/java/android/view/contentcapture/OWNERS +njagar@google.com +williamluh@google.com +aaronjosephs@google.com diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 1840bcb358a0..4742f1ed8219 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -625,8 +625,7 @@ public interface InputConnection { * the text you are providing so it is not possible to correctly * specify locations there. * @param textAttribute The extra information about the text. - * @return true on success, false if the input connection is no longer - * + * @return true on success, false if the input connection is no longer valid. */ default boolean setComposingText(@NonNull CharSequence text, int newCursorPosition, @Nullable TextAttribute textAttribute) { @@ -753,7 +752,7 @@ public interface InputConnection { * you are providing so it is not possible to correctly specify * locations there. * @param textAttribute The extra information about the text. - * @return true on success, false if the input connection is no longer + * @return true on success, false if the input connection is no longer valid. */ default boolean commitText(@NonNull CharSequence text, int newCursorPosition, @Nullable TextAttribute textAttribute) { diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 0e66f7ac47b7..806a59334689 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -878,15 +878,18 @@ public final class InputMethodInfo implements Parcelable { /** * Returns {@link Intent} for IME language settings activity with - * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS}, - * else <code>null</code> if - * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined. + * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS}. If + * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined, tries to + * fall back to the IME general settings activity. If + * {@link android.R.styleable#InputMethod_settingsActivity} is also not defined, + * returns {code null}. * * <p>To launch IME language settings, use this method to get the {@link Intent} to launch * the IME language settings activity.</p> * <p>e.g.<pre><code>startActivity(createImeLanguageSettingsActivityIntent());</code></pre></p> * * @attr ref R.styleable#InputMethod_languageSettingsActivity + * @attr ref R.styleable#InputMethod_settingsActivity */ @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API) @Nullable diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index d12eda35c745..fe2651030789 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -741,9 +741,17 @@ public abstract class WebSettings { public abstract boolean getUseWideViewPort(); /** - * Sets whether the WebView whether supports multiple windows. If set to - * true, {@link WebChromeClient#onCreateWindow} must be implemented by the - * host application. The default is {@code false}. + * Sets whether the WebView should support multiple windows. + * + * <p>If set to {@code true}, the {@link WebChromeClient#onCreateWindow} + * callback must be implemented by the application to handle the + * creation of new windows. + * + * <p>The default is {@code false}. When multiple window support is disabled, + * requests to open new windows (either from the {@code window.open()} + * JavaScript API or from links with {@code target="_blank"}) will instead + * be treated as top-level navigations, replacing the current page in the + * same WebView. * * @param support whether to support multiple windows */ @@ -1338,18 +1346,24 @@ public abstract class WebSettings { } /** - * Tells JavaScript to open windows automatically. This applies to the - * JavaScript function {@code window.open()}. The default is {@code false}. + * Allows JavaScript to open windows without a user gesture. This applies to + * the JavaScript function {@code window.open()}. The default is + * {@code false}: attempts without a user gesture will fail and do nothing. + * <p> + * This is not affected by the {@link #setSupportMultipleWindows} setting; + * the user gesture requirement is enforced even if multiple windows are + * disabled. * - * @param flag {@code true} if JavaScript can open windows automatically + * @param flag {@code true} if JavaScript can open windows without a user + * gesture. */ public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean flag); /** - * Gets whether JavaScript can open windows automatically. + * Gets whether JavaScript can open windows without a user gesture. * - * @return {@code true} if JavaScript can open windows automatically during - * {@code window.open()} + * @return {@code true} if JavaScript can open windows without a user + * gesture using {@code window.open()} * @see #setJavaScriptCanOpenWindowsAutomatically */ public abstract boolean getJavaScriptCanOpenWindowsAutomatically(); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index d28c953fe0bd..03a26722da8f 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -474,7 +474,11 @@ public class Editor { private final AccessibilitySmartActions mA11ySmartActions; private InsertModeController mInsertModeController; - Editor(TextView textView) { + /** + * @hide + */ + @VisibleForTesting + public Editor(TextView textView) { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. mTextView.setFilters(mTextView.getFilters()); @@ -3206,16 +3210,6 @@ public class Editor { } } - final int menuItemOrderUndo = 2; - final int menuItemOrderRedo = 3; - final int menuItemOrderCut = 4; - final int menuItemOrderCopy = 5; - final int menuItemOrderPaste = 6; - final int menuItemOrderPasteAsPlainText = 7; - final int menuItemOrderSelectAll = 8; - final int menuItemOrderShare = 9; - final int menuItemOrderAutofill = 10; - menu.setOptionalIconsVisible(true); menu.setGroupDividerEnabled(true); @@ -3224,7 +3218,18 @@ public class Editor { final int keyboard = mTextView.getResources().getConfiguration().keyboard; menu.setQwertyMode(keyboard == Configuration.KEYBOARD_QWERTY); - final TypedArray a = mTextView.getContext().obtainStyledAttributes(new int[] { + setTextContextMenuItems(menu); + + mPreserveSelection = true; + + // No-op for the old context menu because it doesn't have icons. + adjustIconSpacing(menu); + } + + /** @hide */ + @VisibleForTesting + public void setTextContextMenuItems(ContextMenu menu) { + final TypedArray a = mTextView.getContext().obtainStyledAttributes(new int[]{ // TODO: Make Undo/Redo be public attribute. com.android.internal.R.attr.actionModeUndoDrawable, com.android.internal.R.attr.actionModeRedoDrawable, @@ -3235,6 +3240,16 @@ public class Editor { android.R.attr.actionModeShareDrawable, }); + final int menuItemOrderUndo = 2; + final int menuItemOrderRedo = 3; + final int menuItemOrderCut = 4; + final int menuItemOrderCopy = 5; + final int menuItemOrderPaste = 6; + final int menuItemOrderPasteAsPlainText = 7; + final int menuItemOrderSelectAll = 8; + final int menuItemOrderShare = 9; + final int menuItemOrderAutofill = 10; + menu.add(CONTEXT_MENU_GROUP_UNDO_REDO, TextView.ID_UNDO, menuItemOrderUndo, com.android.internal.R.string.undo) .setAlphabeticShortcut('z') @@ -3291,12 +3306,7 @@ public class Editor { .setEnabled(mTextView.canRequestAutofill() && (selected == null || selected.isEmpty())) .setOnMenuItemClickListener(mOnContextMenuItemClickListener); - - mPreserveSelection = true; a.recycle(); - - // No-op for the old context menu because it doesn't have icons. - adjustIconSpacing(menu); } /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 61ecc6264ffa..72b268b440b5 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -12255,7 +12255,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return selectionMin >= 0 && selectionMax > 0 && selectionMin != selectionMax; } - String getSelectedText() { + /** + * @hide + */ + @VisibleForTesting + public String getSelectedText() { if (!hasSelection()) { return null; } @@ -14080,7 +14084,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener structure.setInputType(getInputType()); } - boolean canRequestAutofill() { + /** + * @hide + */ + @VisibleForTesting + public boolean canRequestAutofill() { if (!isAutofillable()) { return false; } diff --git a/core/java/android/window/flags/wallpaper_manager.aconfig b/core/java/android/window/flags/wallpaper_manager.aconfig index 01c78a0bfb1d..8c6721a7e96a 100644 --- a/core/java/android/window/flags/wallpaper_manager.aconfig +++ b/core/java/android/window/flags/wallpaper_manager.aconfig @@ -39,3 +39,13 @@ flag { description: "Prevent the system from sending visibility event on display state change." bug: "331725519" } + +flag { + name: "no_duplicate_surface_destroyed_events" + namespace: "systemui" + description: "Prevent the system from sending onSurfaceDestroyed() twice." + bug: "344461715" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 9aeccf4c3d9b..61ee13a2693c 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -91,6 +91,14 @@ flag { } flag { + name: "transit_tracker_plumbing" + namespace: "windowing_frontend" + description: "Plumb and collect on transition tracking object instead of singleton" + bug: "325114242" + is_fixed_read_only: true +} + +flag { name: "transit_ready_tracking" namespace: "windowing_frontend" description: "Enable accurate transition readiness tracking" @@ -202,6 +210,14 @@ flag { } flag { + name: "system_ui_immersive_confirmation_dialog" + namespace: "windowing_frontend" + description: "Enable the implementation of the immersive confirmation dialog on system UI side by default" + bug: "359713629" + is_fixed_read_only: true +} + +flag { name: "ensure_wallpaper_in_transitions" namespace: "windowing_frontend" description: "Ensure that wallpaper window tokens are always present/available for collection in transitions" diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java index 27eebbef6245..ce17d788f93b 100644 --- a/core/java/com/android/internal/app/LocalePickerWithRegion.java +++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java @@ -74,6 +74,7 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O * @param locale the locale picked. */ void onLocaleSelected(LocaleStore.LocaleInfo locale); + default void onParentLocaleSelected(LocaleStore.LocaleInfo locale) {} } /** @@ -292,7 +293,7 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O mListener, locale, mTranslatedOnly /* translate only */, mOnActionExpandListener, this.mLocalePickerCollector); } - + mListener.onParentLocaleSelected(locale); if (selector != null) { getFragmentManager().beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index 33610a09b7c8..c7e1fba66d7f 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -396,6 +396,9 @@ public class InteractionJankMonitor { int cujType = conf.mCujType; if (!shouldMonitor()) { return false; + } else if (!conf.hasValidView()) { + Log.w(TAG, "The view has since become invalid, aborting the CUJ."); + return false; } RunningTracker tracker = putTrackerIfNoCurrent(cujType, () -> diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index ec004d07c781..0d0207ff7c0e 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -418,6 +418,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mElevation = preservedWindow.getElevation(); mLoadElevation = false; mForceDecorInstall = true; + mDecorFitsSystemWindows = preservedWindow.decorFitsSystemWindows(); setSystemBarAppearance(preservedWindow.getSystemBarAppearance()); // If we're preserving window, carry over the app token from the preserved // window, as we'll be skipping the addView in handleResumeActivity(), and diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java index 572a599dc8f5..fcc302331dae 100644 --- a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java @@ -48,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; @@ -423,6 +424,14 @@ public class LegacyProtoLogImpl implements IProtoLog { for (IProtoLogGroup group : protoLogGroups) { mLogGroups.put(group.name(), group); } + + final var hasGroupsLoggingToLogcat = Arrays.stream(protoLogGroups) + .anyMatch(IProtoLogGroup::isLogToLogcat); + + final ILogger logger = (msg) -> Slog.i(TAG, msg); + if (hasGroupsLoggingToLogcat) { + mViewerConfig.loadViewerConfig(logger, mLegacyViewerConfigFilename); + } } } diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java index cb20ceb5484b..79a5469956df 100644 --- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java @@ -16,6 +16,7 @@ package com.android.internal.protolog; +import static android.content.Context.PROTOLOG_SERVICE; import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STACKTRACE; import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STRING_ARGS; import static android.internal.perfetto.protos.ProfileCommon.InternedString.IID; @@ -46,6 +47,8 @@ import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket import android.annotation.NonNull; import android.annotation.Nullable; import android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.ShellCommand; import android.os.SystemClock; import android.text.TextUtils; @@ -76,6 +79,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.UUID; @@ -103,36 +107,45 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto private final ProtoLogViewerConfigReader mViewerConfigReader; @Nullable private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider; + @NonNull private final TreeMap<String, IProtoLogGroup> mLogGroups = new TreeMap<>(); + @NonNull private final Runnable mCacheUpdater; + @Nullable // null when the flag android.tracing.client_side_proto_logging is not flipped + private final IProtoLogService mProtoLogService; + + @NonNull private final int[] mDefaultLogLevelCounts = new int[LogLevel.values().length]; + @NonNull private final Map<String, int[]> mLogLevelCounts = new ArrayMap<>(); + @NonNull private final Map<String, Integer> mCollectStackTraceGroupCounts = new ArrayMap<>(); private final Lock mBackgroundServiceLock = new ReentrantLock(); private ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor(); - public PerfettoProtoLogImpl(@NonNull String viewerConfigFilePath, Runnable cacheUpdater) { - this(() -> { - try { - return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); - } catch (FileNotFoundException e) { - throw new RuntimeException("Failed to load viewer config file " + viewerConfigFilePath, e); - } - }, cacheUpdater); + public PerfettoProtoLogImpl() { + this(null, null, null, () -> {}); } - public PerfettoProtoLogImpl() { - this(null, null, () -> {}); + public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater) { + this(null, null, null, cacheUpdater); } public PerfettoProtoLogImpl( - @NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider, - Runnable cacheUpdater - ) { - this(viewerConfigInputStreamProvider, - new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider), + @NonNull String viewerConfigFilePath, + @NonNull Runnable cacheUpdater) { + this(viewerConfigFilePath, + null, + new ProtoLogViewerConfigReader(() -> { + try { + return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); + } catch (FileNotFoundException e) { + throw new RuntimeException( + "Failed to load viewer config file " + viewerConfigFilePath, e); + } + }), cacheUpdater); } @@ -140,8 +153,20 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto public PerfettoProtoLogImpl( @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider, @Nullable ProtoLogViewerConfigReader viewerConfigReader, - Runnable cacheUpdater - ) { + @NonNull Runnable cacheUpdater) { + this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater); + } + + private PerfettoProtoLogImpl( + @Nullable String viewerConfigFilePath, + @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider, + @Nullable ProtoLogViewerConfigReader viewerConfigReader, + @NonNull Runnable cacheUpdater) { + if (viewerConfigFilePath != null && viewerConfigInputStreamProvider != null) { + throw new RuntimeException("Only one of viewerConfigFilePath and " + + "viewerConfigInputStreamProvider can be set"); + } + Producer.init(InitArguments.DEFAULTS); DataSourceParams params = new DataSourceParams.Builder() @@ -153,6 +178,27 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider; this.mViewerConfigReader = viewerConfigReader; this.mCacheUpdater = cacheUpdater; + + if (android.tracing.Flags.clientSideProtoLogging()) { + mProtoLogService = + IProtoLogService.Stub.asInterface(ServiceManager.getService(PROTOLOG_SERVICE)); + Objects.requireNonNull(mProtoLogService, + "ServiceManager returned a null ProtoLog service"); + + try { + var args = new ProtoLogService.RegisterClientArgs(); + + if (viewerConfigFilePath != null) { + args.setViewerConfigFile(viewerConfigFilePath); + } + + mProtoLogService.registerClient(this, args); + } catch (RemoteException e) { + throw new RuntimeException("Failed to register ProtoLog client"); + } + } else { + mProtoLogService = null; + } } /** @@ -355,7 +401,9 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto Log.e(LOG_TAG, "Failed to wait for tracing to finish", e); } - dumpViewerConfig(); + if (!android.tracing.Flags.clientSideProtoLogging()) { + dumpViewerConfig(); + } Log.d(LOG_TAG, "Finished onTracingFlush"); } @@ -451,7 +499,8 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto os.write(GROUP_ID, pis.readInt(GROUP_ID)); break; case (int) LOCATION: - os.write(LOCATION, pis.readInt(LOCATION)); + os.write(LOCATION, pis.readString(LOCATION)); + break; default: throw new RuntimeException( "Unexpected field id " + pis.getFieldNumber()); @@ -690,7 +739,7 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto return UUID.nameUUIDFromBytes(fullStringIdentifier.getBytes()).getMostSignificantBits(); } - private static final int STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL = 12; + private static final int STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL = 6; private String collectStackTrace() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java index 77ca7ce91b22..8659a8ffeb97 100644 --- a/core/java/com/android/internal/protolog/ProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java @@ -111,7 +111,7 @@ public class ProtoLogImpl { // TODO(b/353530422): Remove - temporary fix to unblock b/352290057 // In so tests the viewer config file might not exist in which we don't // want to provide config path to the user - sServiceInstance = new PerfettoProtoLogImpl(null, null, sCacheUpdater); + sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater); } else { sServiceInstance = new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater); } diff --git a/core/java/com/android/internal/util/RateLimitingCache.java b/core/java/com/android/internal/util/RateLimitingCache.java new file mode 100644 index 000000000000..9916076fd0ef --- /dev/null +++ b/core/java/com/android/internal/util/RateLimitingCache.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import android.os.SystemClock; + +/** + * A speed/rate limiting cache that's used to cache a value to be returned as long as period hasn't + * elapsed and then fetches a new value after period has elapsed. Use this when AIDL calls are + * expensive but the value returned by those APIs don't change often enough (or the recency doesn't + * matter as much), to incur the cost every time. This class maintains the last fetch time and + * fetches a new value when period has passed. Do not use this for API calls that have side-effects. + * <p> + * By passing in an optional <code>count</code> during creation, this can be used as a rate + * limiter that allows up to <code>count</code> calls per period to be passed on to the query + * and then the cached value is returned for the remainder of the period. It uses a simple fixed + * window method to track rate. Use a window and count appropriate for bursts of calls and for + * high latency/cost of the AIDL call. + * + * @param <Value> The type of the return value + * @hide + */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass +public class RateLimitingCache<Value> { + + private volatile Value mCurrentValue; + private volatile long mLastTimestamp; // Can be last fetch time or window start of fetch time + private final long mPeriodMillis; // window size + private final int mLimit; // max per window + private int mCount = 0; // current count within window + private long mRandomOffset; // random offset to avoid batching of AIDL calls at window boundary + + /** + * The interface to fetch the actual value, if the cache is null or expired. + * @hide + * @param <V> The return value type + */ + public interface ValueFetcher<V> { + /** Called when the cache needs to be updated. + * @return the latest value fetched from the source + */ + V fetchValue(); + } + + /** + * Create a speed limiting cache that returns the same value until periodMillis has passed + * and then fetches a new value via the {@link ValueFetcher}. + * + * @param periodMillis time to wait before fetching a new value. Use a negative period to + * indicate the value never changes and is fetched only once and + * cached. A value of 0 will mean always fetch a new value. + */ + public RateLimitingCache(long periodMillis) { + this(periodMillis, 1); + } + + /** + * Create a rate-limiting cache that allows up to <code>count</code> number of AIDL calls per + * period before it starts returning a cached value. The count resets when the next period + * begins. + * + * @param periodMillis the window of time in which <code>count</code> calls will fetch the + * newest value from the AIDL call. + * @param count how many times during the period it's ok to forward the request to the fetcher + * in the {@link #get(ValueFetcher)} method. + */ + public RateLimitingCache(long periodMillis, int count) { + mPeriodMillis = periodMillis; + mLimit = count; + if (mLimit > 1 && periodMillis > 1) { + mRandomOffset = (long) (Math.random() * (periodMillis / 2)); + } + } + + /** + * Returns the current time in <code>elapsedRealtime</code>. Can be overridden to use + * a different timebase that is monotonically increasing; for example, uptimeMillis() + * @return a monotonically increasing time in milliseconds + */ + protected long getTime() { + return SystemClock.elapsedRealtime(); + } + + /** + * Returns either the cached value, if called more frequently than the specific rate, or + * a new value is fetched and cached. Warning: if the caller is likely to mutate the returned + * object, override this method and make a clone before returning it. + * @return the cached or latest value + */ + public Value get(ValueFetcher<Value> query) { + // If the value never changes + if (mPeriodMillis < 0 && mLastTimestamp != 0) { + return mCurrentValue; + } + + synchronized (this) { + // Get the current time and add a random offset to avoid colliding with other + // caches with similar harmonic window boundaries + final long now = getTime() + mRandomOffset; + final boolean newWindow = now - mLastTimestamp >= mPeriodMillis; + if (newWindow || mCount < mLimit) { + // Fetch a new value + mCurrentValue = query.fetchValue(); + + // If rate limiting, set timestamp to start of this window + if (mLimit > 1) { + mLastTimestamp = now - (now % mPeriodMillis); + } else { + mLastTimestamp = now; + } + + if (newWindow) { + mCount = 1; + } else { + mCount++; + } + } + return mCurrentValue; + } + } +} diff --git a/core/jni/android_database_SQLiteRawStatement.cpp b/core/jni/android_database_SQLiteRawStatement.cpp index 961486474821..85a6bdf95928 100644 --- a/core/jni/android_database_SQLiteRawStatement.cpp +++ b/core/jni/android_database_SQLiteRawStatement.cpp @@ -72,14 +72,17 @@ static void throwInvalidParameter(JNIEnv *env, jlong stmtPtr, jint index) { // This throws a SQLiteBindOrColumnIndexOutOfRangeException if the column index is out -// of bounds. -static void throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) { +// of bounds. It returns true if an exception was thrown. +static bool throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) { if (col < 0 || col >= sqlite3_data_count(stmt(stmtPtr))) { int count = sqlite3_data_count(stmt(stmtPtr)); std::string message = android::base::StringPrintf( "column index %d out of bounds [0,%d]", col, count - 1); char const * errmsg = sqlite3_errstr(SQLITE_RANGE); throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str()); + return true; + } else { + return false; } } @@ -216,12 +219,16 @@ static void bindText(JNIEnv* env, jclass, jlong stmtPtr, jint index, jstring val static jint columnType(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } return sqlite3_column_type(stmt(stmtPtr), col); } static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return nullptr; + } const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(stmt(stmtPtr), col)); if (name == nullptr) { throw_sqlite3_exception(env, db(stmtPtr), "error fetching columnName()"); @@ -232,14 +239,18 @@ static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) { } static jint columnBytes(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } int r = sqlite3_column_bytes16(stmt(stmtPtr), col); throwIfError(env, stmtPtr); return r; } static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return nullptr; + } const void* blob = sqlite3_column_blob(stmt(stmtPtr), col); if (blob == nullptr) { if (throwIfError(env, stmtPtr)) { @@ -262,7 +273,9 @@ static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) { static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col, jbyteArray buffer, jint offset, jint length, jint srcOffset) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } const void* blob = sqlite3_column_blob(stmt(stmtPtr), col); if (blob == nullptr) { throwIfError(env, stmtPtr); @@ -281,22 +294,30 @@ static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col, } static jdouble columnDouble(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } return sqlite3_column_double(stmt(stmtPtr), col); } static jint columnInt(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } return sqlite3_column_int(stmt(stmtPtr), col); } static jlong columnLong(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return 0; + } return sqlite3_column_int64(stmt(stmtPtr), col); } static jstring columnText(JNIEnv* env, jclass, jlong stmtPtr, jint col) { - throwIfInvalidColumn(env, stmtPtr, col); + if (throwIfInvalidColumn(env, stmtPtr, col)) { + return nullptr; + } const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(stmt(stmtPtr), col)); if (text == nullptr) { throwIfError(env, stmtPtr); diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp index 84ca1ba6ad7c..7a4670f4e49d 100644 --- a/core/jni/android_os_SELinux.cpp +++ b/core/jni/android_os_SELinux.cpp @@ -53,7 +53,7 @@ selabel_handle* GetSELabelHandle() { } struct SecurityContext_Delete { - void operator()(security_context_t p) const { + void operator()(char* p) const { freecon(p); } }; @@ -111,7 +111,7 @@ static jstring fileSelabelLookup(JNIEnv* env, jobject, jstring pathStr) { return NULL; } - security_context_t tmp = NULL; + char* tmp = NULL; if (selabel_lookup(selabel_handle, &tmp, path_c_str, S_IFREG) != 0) { ALOGE("fileSelabelLookup => selabel_lookup for %s failed: %d", path_c_str, errno); return NULL; @@ -138,7 +138,7 @@ static jstring getFdConInner(JNIEnv *env, jobject fileDescriptor, bool isSocket) return NULL; } - security_context_t tmp = NULL; + char* tmp = NULL; int ret; if (isSocket) { ret = getpeercon(fd, &tmp); @@ -184,7 +184,7 @@ static jstring getFdCon(JNIEnv *env, jobject, jobject fileDescriptor) { * Function: setFSCreateCon * Purpose: set security context used for creating a new file system object * Parameters: - * context: security_context_t representing the new context of a file system object, + * context: char* representing the new context of a file system object, * set to NULL to return to the default policy behavior * Returns: true on success, false on error * Exception: none @@ -267,7 +267,7 @@ static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { return NULL; } - security_context_t tmp = NULL; + char* tmp = NULL; int ret = getfilecon(path.c_str(), &tmp); Unique_SecurityContext context(tmp); @@ -293,7 +293,7 @@ static jstring getCon(JNIEnv *env, jobject) { return NULL; } - security_context_t tmp = NULL; + char* tmp = NULL; int ret = getcon(&tmp); Unique_SecurityContext context(tmp); @@ -320,7 +320,7 @@ static jstring getPidCon(JNIEnv *env, jobject, jint pid) { return NULL; } - security_context_t tmp = NULL; + char* tmp = NULL; int ret = getpidcon(static_cast<pid_t>(pid), &tmp); Unique_SecurityContext context(tmp); diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 9112d376a32f..284c2997f9a9 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -19,14 +19,6 @@ #include "com_android_internal_os_Zygote.h" -#include <async_safe/log.h> - -// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc -#include <sys/mount.h> -#include <linux/fs.h> -#include <sys/types.h> -#include <dirent.h> - #include <algorithm> #include <array> #include <atomic> @@ -41,19 +33,18 @@ #include <android/fdsan.h> #include <arpa/inet.h> +#include <dirent.h> #include <fcntl.h> #include <grp.h> #include <inttypes.h> #include <malloc.h> #include <mntent.h> -#include <paths.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> -#include <sys/auxv.h> #include <sys/capability.h> -#include <sys/cdefs.h> #include <sys/eventfd.h> +#include <sys/mount.h> #include <sys/personality.h> #include <sys/prctl.h> #include <sys/resource.h> @@ -66,6 +57,7 @@ #include <sys/wait.h> #include <unistd.h> +#include <async_safe/log.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> diff --git a/core/res/Android.bp b/core/res/Android.bp index e900eb2f01ab..bcc0a975b913 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -156,6 +156,7 @@ android_app { generate_product_characteristics_rro: true, flags_packages: [ + "android.app.appfunctions.flags-aconfig", "android.app.contextualsearch.flags-aconfig", "android.content.pm.flags-aconfig", "android.provider.flags-aconfig", @@ -164,6 +165,7 @@ android_app { "com.android.window.flags.window-aconfig", "android.permission.flags-aconfig", "android.os.flags-aconfig", + "android.os.vibrator.flags-aconfig", "android.media.tv.flags-aconfig", ], } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7aeabeed2a08..160f651dbc5c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2617,7 +2617,8 @@ @hide --> <permission android:name="android.permission.VIBRATE_VENDOR_EFFECTS" - android:protectionLevel="signature|privileged" /> + android:protectionLevel="signature|privileged" + android:featureFlag="android.os.vibrator.vendor_vibration_effects" /> <!-- @SystemApi Allows access to the vibrator state. <p>Protection level: signature @@ -8010,6 +8011,41 @@ <permission android:name="android.permission.EXECUTE_APP_ACTION" android:protectionLevel="internal|role" /> + <!-- Must be required by an {@link android.app.appfunctions.AppFunctionService}, + to ensure that only the system can bind to it. + <p>Protection level: signature + @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") --> + <permission android:name="android.permission.BIND_APP_FUNCTION_SERVICE" + android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" + android:protectionLevel="signature" /> + + <!-- @SystemApi Allows a trusted application to perform actions on behalf of users inside of + applications with privacy guarantees from the system. + <p>This permission is currently only granted to system packages in the + {@link android.app.role.SYSTEM_UI_INTELLIGENCE} role which complies with privacy + requirements outlined in the Android CDD section "9.8.6 Content Capture". + <p>Apps are not able to opt-out from caller having this permission. + <p>Protection level: internal|role + @hide + @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") --> + <permission android:name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" + android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" + android:protectionLevel="internal|role" /> + + <!-- @SystemApi Allows an application to perform actions on behalf of users inside of + applications. + <p>This permission is currently only granted to preinstalled / system apps having the + {@link android.app.role.ASSISTANT} role. + <p>Apps contributing app functions can opt to disallow callers with this permission, + limiting to only callers with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} + instead. + <p>Protection level: internal|role + @hide + @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") --> + <permission android:name="android.permission.EXECUTE_APP_FUNCTIONS" + android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" + android:protectionLevel="internal|role" /> + <!-- Allows an application to display its suggestions using the autofill framework. <p>For now, this permission is only granted to the Browser application. <p>Protection level: internal|role @@ -8132,10 +8168,10 @@ <permission android:name="android.permission.MONITOR_STICKY_MODIFIER_STATE" android:protectionLevel="signature" /> - <!-- Allows low-level access to monitor keyboard system shortcuts + <!-- Allows low-level access to manage key gestures. <p>Not for use by third-party applications. @hide --> - <permission android:name="android.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS" + <permission android:name="android.permission.MANAGE_KEY_GESTURES" android:protectionLevel="signature" /> <uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" /> diff --git a/core/res/res/drawable-car/car_activity_resolver_list_background.xml b/core/res/res/drawable-car/car_activity_resolver_list_background.xml deleted file mode 100644 index dbbadd83d9a8..000000000000 --- a/core/res/res/drawable-car/car_activity_resolver_list_background.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright (C) 2024 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid android:color="?attr/colorBackgroundFloating" /> - <corners android:radius="@dimen/car_activity_resolver_corner_radius" /> -</shape>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml b/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml new file mode 100644 index 000000000000..31004ecd0e72 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_animal_paw.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M180,485Q138,485 109,456Q80,427 80,385Q80,343 109,314Q138,285 180,285Q222,285 251,314Q280,343 280,385Q280,427 251,456Q222,485 180,485ZM360,325Q318,325 289,296Q260,267 260,225Q260,183 289,154Q318,125 360,125Q402,125 431,154Q460,183 460,225Q460,267 431,296Q402,325 360,325ZM600,325Q558,325 529,296Q500,267 500,225Q500,183 529,154Q558,125 600,125Q642,125 671,154Q700,183 700,225Q700,267 671,296Q642,325 600,325ZM780,485Q738,485 709,456Q680,427 680,385Q680,343 709,314Q738,285 780,285Q822,285 851,314Q880,343 880,385Q880,427 851,456Q822,485 780,485ZM266,885Q221,885 190.5,850.5Q160,816 160,769Q160,717 195.5,678Q231,639 266,601Q295,570 316,533.5Q337,497 366,465Q388,439 417,422Q446,405 480,405Q514,405 543,421Q572,437 594,463Q622,495 643.5,532Q665,569 694,601Q729,639 764.5,678Q800,717 800,769Q800,816 769.5,850.5Q739,885 694,885Q640,885 587,876Q534,867 480,867Q426,867 373,876Q320,885 266,885Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml b/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml new file mode 100644 index 000000000000..30f01fa9d3b6 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_apartment_building.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M120,840L120,280L280,280L280,120L680,120L680,440L840,440L840,840L520,840L520,680L440,680L440,840L120,840ZM200,760L280,760L280,680L200,680L200,760ZM200,600L280,600L280,520L200,520L200,600ZM200,440L280,440L280,360L200,360L200,440ZM360,600L440,600L440,520L360,520L360,600ZM360,440L440,440L440,360L360,360L360,440ZM360,280L440,280L440,200L360,200L360,280ZM520,600L600,600L600,520L520,520L520,600ZM520,440L600,440L600,360L520,360L520,440ZM520,280L600,280L600,200L520,200L520,280ZM680,760L760,760L760,680L680,680L680,760ZM680,600L760,600L760,520L680,520L680,600Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_book.xml b/core/res/res/drawable/ic_zen_mode_icon_book.xml new file mode 100644 index 000000000000..c30d222da7c1 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_book.xml @@ -0,0 +1,26 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960" + android:autoMirrored="true"> + <path + android:fillColor="@android:color/white" + android:pathData="M560,396L560,328Q593,314 627.5,307Q662,300 700,300Q726,300 751,304Q776,308 800,314L800,378Q776,369 751.5,364.5Q727,360 700,360Q662,360 627,369.5Q592,379 560,396ZM560,616L560,548Q593,534 627.5,527Q662,520 700,520Q726,520 751,524Q776,528 800,534L800,598Q776,589 751.5,584.5Q727,580 700,580Q662,580 627,589Q592,598 560,616ZM560,506L560,438Q593,424 627.5,417Q662,410 700,410Q726,410 751,414Q776,418 800,424L800,488Q776,479 751.5,474.5Q727,470 700,470Q662,470 627,479.5Q592,489 560,506ZM260,640Q307,640 351.5,650.5Q396,661 440,682L440,288Q399,264 353,252Q307,240 260,240Q224,240 188.5,247Q153,254 120,268Q120,268 120,268Q120,268 120,268L120,664Q120,664 120,664Q120,664 120,664Q155,652 189.5,646Q224,640 260,640ZM520,682Q564,661 608.5,650.5Q653,640 700,640Q736,640 770.5,646Q805,652 840,664Q840,664 840,664Q840,664 840,664L840,268Q840,268 840,268Q840,268 840,268Q807,254 771.5,247Q736,240 700,240Q653,240 607,252Q561,264 520,288L520,682ZM480,800Q432,762 376,741Q320,720 260,720Q218,720 177.5,731Q137,742 100,762Q79,773 59.5,761Q40,749 40,726L40,244Q40,233 45.5,223Q51,213 62,208Q108,184 158,172Q208,160 260,160Q318,160 373.5,175Q429,190 480,220Q531,190 586.5,175Q642,160 700,160Q752,160 802,172Q852,184 898,208Q909,213 914.5,223Q920,233 920,244L920,726Q920,749 900.5,761Q881,773 860,762Q823,742 782.5,731Q742,720 700,720Q640,720 584,741Q528,762 480,800ZM280,466Q280,466 280,466Q280,466 280,466L280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466L280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Q280,466 280,466Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_child.xml b/core/res/res/drawable/ic_zen_mode_icon_child.xml new file mode 100644 index 000000000000..d11772ac1db6 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_child.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M580,470Q559,470 544.5,455.5Q530,441 530,420Q530,399 544.5,384.5Q559,370 580,370Q601,370 615.5,384.5Q630,399 630,420Q630,441 615.5,455.5Q601,470 580,470ZM380,470Q359,470 344.5,455.5Q330,441 330,420Q330,399 344.5,384.5Q359,370 380,370Q401,370 415.5,384.5Q430,399 430,420Q430,441 415.5,455.5Q401,470 380,470ZM480,680Q420,680 371.5,647Q323,614 300,560L660,560Q637,614 588.5,647Q540,680 480,680ZM480,840Q405,840 339.5,811.5Q274,783 225.5,734.5Q177,686 148.5,620.5Q120,555 120,480Q120,405 148.5,339.5Q177,274 225.5,225.5Q274,177 339.5,148.5Q405,120 480,120Q555,120 620.5,148.5Q686,177 734.5,225.5Q783,274 811.5,339.5Q840,405 840,480Q840,555 811.5,620.5Q783,686 734.5,734.5Q686,783 620.5,811.5Q555,840 480,840ZM480,760Q596,760 678,678Q760,596 760,480Q760,364 678,282Q596,200 480,200Q474,200 468,200Q462,200 456,202Q450,208 448,215Q446,222 446,230Q446,251 460.5,265.5Q475,280 496,280Q505,280 512.5,277Q520,274 528,274Q540,274 548,283Q556,292 556,304Q556,327 534.5,333.5Q513,340 496,340Q451,340 418.5,307.5Q386,275 386,230Q386,227 386,224Q386,221 387,216Q304,246 252,317Q200,388 200,480Q200,596 282,678Q364,760 480,760ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml b/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml new file mode 100644 index 000000000000..26751262c673 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_classical_building.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M200,680L200,400L280,400L280,680L200,680ZM440,680L440,400L520,400L520,680L440,680ZM80,840L80,760L880,760L880,840L80,840ZM680,680L680,400L760,400L760,680L680,680ZM80,320L80,240L480,40L880,240L880,320L80,320ZM258,240L480,240L702,240L258,240ZM258,240L702,240L480,130L258,240Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_croissant.xml b/core/res/res/drawable/ic_zen_mode_icon_croissant.xml new file mode 100644 index 000000000000..199343d0e502 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_croissant.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M804,678Q821,687 834,674Q847,661 838,644L780,536L738,644L804,678ZM604,640L652,640L748,402Q751,394 746.5,388.5Q742,383 736,380L656,348Q647,345 638.5,350Q630,355 628,364L604,640ZM308,640L356,640L332,364Q330,353 321.5,349Q313,345 304,348L224,380Q216,383 212.5,388.5Q209,394 212,402L308,640ZM156,678L222,644L180,536L122,644Q113,661 126,674Q139,687 156,678ZM436,640L524,640L554,302Q556,293 549.5,286.5Q543,280 534,280L426,280Q418,280 411.5,286.5Q405,293 406,302L436,640ZM138,760Q96,760 68,728.5Q40,697 40,654Q40,642 43.5,630.5Q47,619 52,608L140,440Q126,400 141,361Q156,322 194,306L274,274Q288,269 302,267Q316,265 330,268Q344,239 369,219.5Q394,200 426,200L534,200Q566,200 591,219.5Q616,239 630,268Q644,266 658,267.5Q672,269 686,274L766,306Q806,322 822,361Q838,400 820,438L908,606Q914,617 917,629Q920,641 920,654Q920,699 889.5,729.5Q859,760 814,760Q803,760 792,757.5Q781,755 770,750L708,720L250,720L194,750Q181,757 166.5,758.5Q152,760 138,760ZM480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml b/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml new file mode 100644 index 000000000000..1fa73794eb32 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_fork_and_knife.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M280,880L280,514Q229,500 194.5,458Q160,416 160,360L160,80L240,80L240,360L280,360L280,80L360,80L360,360L400,360L400,80L480,80L480,360Q480,416 445.5,458Q411,500 360,514L360,880L280,880ZM680,880L680,560L560,560L560,280Q560,197 618.5,138.5Q677,80 760,80L760,880L680,880Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml b/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml new file mode 100644 index 000000000000..c6194d529117 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_group_of_people.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M0,720L0,657Q0,614 44,587Q88,560 160,560Q173,560 185,560.5Q197,561 208,563Q194,584 187,607Q180,630 180,655L180,720L0,720ZM240,720L240,655Q240,623 257.5,596.5Q275,570 307,550Q339,530 383.5,520Q428,510 480,510Q533,510 577.5,520Q622,530 654,550Q686,570 703,596.5Q720,623 720,655L720,720L240,720ZM780,720L780,655Q780,629 773.5,606Q767,583 754,563Q765,561 776.5,560.5Q788,560 800,560Q872,560 916,586.5Q960,613 960,657L960,720L780,720ZM325,640L636,640L636,640Q626,620 580.5,605Q535,590 480,590Q425,590 379.5,605Q334,620 325,640ZM160,520Q127,520 103.5,496.5Q80,473 80,440Q80,406 103.5,383Q127,360 160,360Q194,360 217,383Q240,406 240,440Q240,473 217,496.5Q194,520 160,520ZM800,520Q767,520 743.5,496.5Q720,473 720,440Q720,406 743.5,383Q767,360 800,360Q834,360 857,383Q880,406 880,440Q880,473 857,496.5Q834,520 800,520ZM480,480Q430,480 395,445Q360,410 360,360Q360,309 395,274.5Q430,240 480,240Q531,240 565.5,274.5Q600,309 600,360Q600,410 565.5,445Q531,480 480,480ZM480,400Q497,400 508.5,388.5Q520,377 520,360Q520,343 508.5,331.5Q497,320 480,320Q463,320 451.5,331.5Q440,343 440,360Q440,377 451.5,388.5Q463,400 480,400ZM481,640L481,640Q481,640 481,640Q481,640 481,640Q481,640 481,640Q481,640 481,640L481,640ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_headphones.xml b/core/res/res/drawable/ic_zen_mode_icon_headphones.xml new file mode 100644 index 000000000000..f0bc7a211ca5 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_headphones.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M360,840L200,840Q167,840 143.5,816.5Q120,793 120,760L120,480Q120,405 148.5,339.5Q177,274 225.5,225.5Q274,177 339.5,148.5Q405,120 480,120Q555,120 620.5,148.5Q686,177 734.5,225.5Q783,274 811.5,339.5Q840,405 840,480L840,760Q840,793 816.5,816.5Q793,840 760,840L600,840L600,520L760,520L760,480Q760,363 678.5,281.5Q597,200 480,200Q363,200 281.5,281.5Q200,363 200,480L200,520L360,520L360,840ZM280,600L200,600L200,760Q200,760 200,760Q200,760 200,760L280,760L280,600ZM680,600L680,760L760,760Q760,760 760,760Q760,760 760,760L760,600L680,600ZM280,600L280,600L200,600Q200,600 200,600Q200,600 200,600L200,600L280,600ZM680,600L760,600L760,600Q760,600 760,600Q760,600 760,600L680,600Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_heart.xml b/core/res/res/drawable/ic_zen_mode_icon_heart.xml new file mode 100644 index 000000000000..c9b1577d57f4 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_heart.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M480,840L422,788Q321,697 255,631Q189,565 150,512.5Q111,460 95.5,416Q80,372 80,326Q80,232 143,169Q206,106 300,106Q352,106 399,128Q446,150 480,190Q514,150 561,128Q608,106 660,106Q754,106 817,169Q880,232 880,326Q880,372 864.5,416Q849,460 810,512.5Q771,565 705,631Q639,697 538,788L480,840ZM480,732Q576,646 638,584.5Q700,523 736,477.5Q772,432 786,396.5Q800,361 800,326Q800,266 760,226Q720,186 660,186Q613,186 573,212.5Q533,239 518,280L518,280L442,280L442,280Q427,239 387,212.5Q347,186 300,186Q240,186 200,226Q160,266 160,326Q160,361 174,396.5Q188,432 224,477.5Q260,523 322,584.5Q384,646 480,732ZM480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459L480,459L480,459L480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_house.xml b/core/res/res/drawable/ic_zen_mode_icon_house.xml new file mode 100644 index 000000000000..e25d194eb8d0 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_house.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M160,840L160,465L88,520L40,456L160,364L160,240L240,240L240,303L480,120L920,456L872,519L800,465L800,840L160,840ZM240,760L440,760L440,600L520,600L520,760L720,760L720,404L480,221L240,404L240,760ZM160,200Q160,150 195,115Q230,80 280,80Q297,80 308.5,68.5Q320,57 320,40L400,40Q400,90 365,125Q330,160 280,160Q263,160 251.5,171.5Q240,183 240,200L160,200ZM240,760L440,760L440,760L520,760L520,760L720,760L720,760L480,760L240,760Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml b/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml new file mode 100644 index 000000000000..602e60d0824a --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_lightbulb.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M480,880Q454,880 433,867.5Q412,855 400,834L400,834Q367,834 343.5,810.5Q320,787 320,754L320,612Q261,573 225.5,509Q190,445 190,370Q190,249 274.5,164.5Q359,80 480,80Q601,80 685.5,164.5Q770,249 770,370Q770,447 734.5,510Q699,573 640,612L640,754Q640,787 616.5,810.5Q593,834 560,834L560,834Q548,855 527,867.5Q506,880 480,880ZM400,754L560,754L560,718L400,718L400,754ZM400,678L560,678L560,640L400,640L400,678ZM392,560L450,560L450,452L362,364L404,322L480,398L556,322L598,364L510,452L510,560L568,560Q622,534 656,483.5Q690,433 690,370Q690,282 629,221Q568,160 480,160Q392,160 331,221Q270,282 270,370Q270,433 304,483.5Q338,534 392,560ZM480,398L480,398L480,398L480,398L480,398L480,398L480,398L480,398L480,398ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360L480,360Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_lotus_flower.xml b/core/res/res/drawable/ic_zen_mode_icon_lotus_flower.xml new file mode 100644 index 000000000000..c1afd44ecfc4 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_lotus_flower.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M480,880Q407,871 335,840.5Q263,810 206.5,753Q150,696 115,609Q80,522 80,400L80,360L120,360Q171,360 225,373Q279,386 326,412Q338,326 380.5,235.5Q423,145 480,80Q537,145 579.5,235.5Q622,326 634,412Q681,386 735,373Q789,360 840,360L880,360L880,400Q880,522 845,609Q810,696 753.5,753Q697,810 625.5,840.5Q554,871 480,880ZM478,798Q467,632 379.5,547Q292,462 162,442Q173,613 263.5,697Q354,781 478,798ZM480,544Q495,522 516.5,498.5Q538,475 558,458Q556,401 535.5,339Q515,277 480,218Q445,277 424.5,339Q404,401 402,458Q422,475 444,498.5Q466,522 480,544ZM558,780Q595,768 635,745Q675,722 709.5,682.5Q744,643 768.5,584Q793,525 798,442Q704,456 633,504.5Q562,553 524,628Q536,660 544.5,698Q553,736 558,780ZM480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544ZM558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780ZM478,798Q478,798 478,798Q478,798 478,798Q478,798 478,798Q478,798 478,798ZM524,628L524,628Q524,628 524,628Q524,628 524,628L524,628L524,628L524,628Q524,628 524,628Q524,628 524,628L524,628Q524,628 524,628Q524,628 524,628ZM480,880L480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880L480,880Q480,880 480,880Q480,880 480,880L480,880Q480,880 480,880Q480,880 480,880L480,880Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_palette.xml b/core/res/res/drawable/ic_zen_mode_icon_palette.xml new file mode 100644 index 000000000000..f31704de1498 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_palette.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M480,880Q398,880 325,848.5Q252,817 197.5,762.5Q143,708 111.5,635Q80,562 80,480Q80,397 112.5,324Q145,251 200.5,197Q256,143 330,111.5Q404,80 488,80Q568,80 639,107.5Q710,135 763.5,183.5Q817,232 848.5,298.5Q880,365 880,442Q880,557 810,618.5Q740,680 640,680L566,680Q557,680 553.5,685Q550,690 550,696Q550,708 565,730.5Q580,753 580,782Q580,832 552.5,856Q525,880 480,880ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM260,520Q286,520 303,503Q320,486 320,460Q320,434 303,417Q286,400 260,400Q234,400 217,417Q200,434 200,460Q200,486 217,503Q234,520 260,520ZM380,360Q406,360 423,343Q440,326 440,300Q440,274 423,257Q406,240 380,240Q354,240 337,257Q320,274 320,300Q320,326 337,343Q354,360 380,360ZM580,360Q606,360 623,343Q640,326 640,300Q640,274 623,257Q606,240 580,240Q554,240 537,257Q520,274 520,300Q520,326 537,343Q554,360 580,360ZM700,520Q726,520 743,503Q760,486 760,460Q760,434 743,417Q726,400 700,400Q674,400 657,417Q640,434 640,460Q640,486 657,503Q674,520 700,520ZM480,800Q489,800 494.5,795Q500,790 500,782Q500,768 485,749Q470,730 470,692Q470,650 499,625Q528,600 570,600L640,600Q706,600 753,561.5Q800,523 800,442Q800,321 707.5,240.5Q615,160 488,160Q352,160 256,253Q160,346 160,480Q160,613 253.5,706.5Q347,800 480,800Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_running.xml b/core/res/res/drawable/ic_zen_mode_icon_running.xml new file mode 100644 index 000000000000..472b04e24bc0 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_running.xml @@ -0,0 +1,26 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960" + android:autoMirrored="true"> + <path + android:fillColor="@android:color/white" + android:pathData="M520,920L520,680L436,600L396,776L120,720L136,640L328,680L392,356L320,384L320,520L240,520L240,332L398,264Q433,249 449.5,244.5Q466,240 480,240Q501,240 519,251Q537,262 548,280L588,344Q614,386 658.5,413Q703,440 760,440L760,520Q694,520 636.5,492.5Q579,465 540,420L516,540L600,620L600,920L520,920ZM540,220Q507,220 483.5,196.5Q460,173 460,140Q460,107 483.5,83.5Q507,60 540,60Q573,60 596.5,83.5Q620,107 620,140Q620,173 596.5,196.5Q573,220 540,220Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml b/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml new file mode 100644 index 000000000000..92cec4dde7b7 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_shopping_cart.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M280,880Q247,880 223.5,856.5Q200,833 200,800Q200,767 223.5,743.5Q247,720 280,720Q313,720 336.5,743.5Q360,767 360,800Q360,833 336.5,856.5Q313,880 280,880ZM680,880Q647,880 623.5,856.5Q600,833 600,800Q600,767 623.5,743.5Q647,720 680,720Q713,720 736.5,743.5Q760,767 760,800Q760,833 736.5,856.5Q713,880 680,880ZM246,240L342,440L622,440Q622,440 622,440Q622,440 622,440L732,240Q732,240 732,240Q732,240 732,240L246,240ZM208,160L798,160Q821,160 833,180.5Q845,201 834,222L692,478Q681,498 662.5,509Q644,520 622,520L324,520L280,600Q280,600 280,600Q280,600 280,600L760,600L760,680L280,680Q235,680 212,640.5Q189,601 210,562L264,464L120,160L40,160L40,80L170,80L208,160ZM342,440L342,440L622,440Q622,440 622,440Q622,440 622,440L622,440L342,440Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml b/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml new file mode 100644 index 000000000000..1746e20a6aae --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_snowflake.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M440,880L440,714L310,842L254,786L440,600L440,520L360,520L174,706L118,650L246,520L80,520L80,440L246,440L118,310L174,254L360,440L440,440L440,360L254,174L310,118L440,246L440,80L520,80L520,246L650,118L706,174L520,360L520,440L600,440L786,254L842,310L714,440L880,440L880,520L714,520L842,650L786,706L600,520L520,520L520,600L706,786L650,842L520,714L520,880L440,880Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml b/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml new file mode 100644 index 000000000000..4be98abd9369 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_speech_bubble.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M80,880L80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM206,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L160,160Q160,160 160,160Q160,160 160,160L160,685L206,640ZM160,640L160,640L160,160Q160,160 160,160Q160,160 160,160L160,160Q160,160 160,160Q160,160 160,160L160,640Q160,640 160,640Q160,640 160,640Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_train.xml b/core/res/res/drawable/ic_zen_mode_icon_train.xml new file mode 100644 index 000000000000..b6f3445468a5 --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_train.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M160,620L160,240Q160,187 187.5,155.5Q215,124 260,107.5Q305,91 362.5,85.5Q420,80 480,80Q546,80 604.5,85.5Q663,91 706.5,107.5Q750,124 775,155.5Q800,187 800,240L800,620Q800,679 759.5,719.5Q719,760 660,760L720,820L720,840L640,840L560,760L400,760L320,840L240,840L240,820L300,760Q241,760 200.5,719.5Q160,679 160,620ZM480,160Q374,160 325,172.5Q276,185 258,200L706,200Q691,183 641.5,171.5Q592,160 480,160ZM240,400L440,400L440,280L240,280L240,400ZM660,480L300,480Q274,480 257,480Q240,480 240,480L240,480L720,480L720,480Q720,480 703,480Q686,480 660,480ZM520,400L720,400L720,280L520,280L520,400ZM340,640Q366,640 383,623Q400,606 400,580Q400,554 383,537Q366,520 340,520Q314,520 297,537Q280,554 280,580Q280,606 297,623Q314,640 340,640ZM620,640Q646,640 663,623Q680,606 680,580Q680,554 663,537Q646,520 620,520Q594,520 577,537Q560,554 560,580Q560,606 577,623Q594,640 620,640ZM300,680L660,680Q686,680 703,663Q720,646 720,620L720,480L240,480L240,620Q240,646 257,663Q274,680 300,680ZM480,200Q592,200 641.5,200Q691,200 706,200L258,200Q276,200 325,200Q374,200 480,200Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_icon_tv.xml b/core/res/res/drawable/ic_zen_mode_icon_tv.xml new file mode 100644 index 000000000000..eaa920aa37cc --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_tv.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?android:attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M320,840L320,760L160,760Q127,760 103.5,736.5Q80,713 80,680L80,200Q80,167 103.5,143.5Q127,120 160,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,680Q880,713 856.5,736.5Q833,760 800,760L640,760L640,840L320,840ZM160,680L800,680Q800,680 800,680Q800,680 800,680L800,200Q800,200 800,200Q800,200 800,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680ZM160,680Q160,680 160,680Q160,680 160,680L160,200Q160,200 160,200Q160,200 160,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680Z" /> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_zen_mode_type_unknown.xml b/core/res/res/drawable/ic_zen_mode_type_unknown.xml index c1afd44ecfc4..04df5f91fd68 100644 --- a/core/res/res/drawable/ic_zen_mode_type_unknown.xml +++ b/core/res/res/drawable/ic_zen_mode_type_unknown.xml @@ -21,5 +21,5 @@ Copyright (C) 2024 The Android Open Source Project android:viewportWidth="960"> <path android:fillColor="@android:color/white" - android:pathData="M480,880Q407,871 335,840.5Q263,810 206.5,753Q150,696 115,609Q80,522 80,400L80,360L120,360Q171,360 225,373Q279,386 326,412Q338,326 380.5,235.5Q423,145 480,80Q537,145 579.5,235.5Q622,326 634,412Q681,386 735,373Q789,360 840,360L880,360L880,400Q880,522 845,609Q810,696 753.5,753Q697,810 625.5,840.5Q554,871 480,880ZM478,798Q467,632 379.5,547Q292,462 162,442Q173,613 263.5,697Q354,781 478,798ZM480,544Q495,522 516.5,498.5Q538,475 558,458Q556,401 535.5,339Q515,277 480,218Q445,277 424.5,339Q404,401 402,458Q422,475 444,498.5Q466,522 480,544ZM558,780Q595,768 635,745Q675,722 709.5,682.5Q744,643 768.5,584Q793,525 798,442Q704,456 633,504.5Q562,553 524,628Q536,660 544.5,698Q553,736 558,780ZM480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544Q480,544 480,544ZM558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780Q558,780 558,780ZM478,798Q478,798 478,798Q478,798 478,798Q478,798 478,798Q478,798 478,798ZM524,628L524,628Q524,628 524,628Q524,628 524,628L524,628L524,628L524,628Q524,628 524,628Q524,628 524,628L524,628Q524,628 524,628Q524,628 524,628ZM480,880L480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880Q480,880 480,880L480,880Q480,880 480,880Q480,880 480,880L480,880Q480,880 480,880Q480,880 480,880L480,880Z" /> + android:pathData="M368,640L480,556L590,640L548,504L660,416L524,416L480,280L436,416L300,416L410,504L368,640ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,585Q80,574 87,566Q94,558 105,556Q129,548 144.5,527Q160,506 160,480Q160,454 144.5,433Q129,412 105,404Q94,402 87,394Q80,386 80,375L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,375Q880,386 873,394Q866,402 855,404Q831,412 815.5,433Q800,454 800,480Q800,506 815.5,527Q831,548 855,556Q866,558 873,566Q880,574 880,585L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM160,720L800,720Q800,720 800,720Q800,720 800,720L800,618Q763,596 741.5,559.5Q720,523 720,480Q720,437 741.5,400.5Q763,364 800,342L800,240Q800,240 800,240Q800,240 800,240L160,240Q160,240 160,240Q160,240 160,240L160,342Q197,364 218.5,400.5Q240,437 240,480Q240,523 218.5,559.5Q197,596 160,618L160,720Q160,720 160,720Q160,720 160,720ZM480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Z" /> </vector>
\ No newline at end of file diff --git a/core/res/res/layout-car/car_resolver_list.xml b/core/res/res/layout-car/car_resolver_list.xml deleted file mode 100644 index 08c98615087b..000000000000 --- a/core/res/res/layout-car/car_resolver_list.xml +++ /dev/null @@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -* Copyright 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. -*/ ---> -<com.android.internal.widget.ResolverDrawerLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="@dimen/car_activity_resolver_width" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:id="@id/contentPanel"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:background="@drawable/car_activity_resolver_list_background"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@drawable/car_activity_resolver_list_background" - android:orientation="horizontal" - android:paddingVertical="@dimen/car_padding_4" - android:paddingHorizontal="@dimen/car_padding_4" > - <TextView - android:id="@+id/profile_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" /> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start" - android:textAppearance="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" /> - </LinearLayout> - - <FrameLayout - android:id="@+id/stub" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - - <TabHost - android:id="@+id/profile_tabhost" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_centerHorizontal="true" - android:background="?android:attr/colorBackgroundFloating"> - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TabWidget - android:id="@android:id/tabs" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - </TabWidget> - <View - android:id="@+id/resolver_tab_divider" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - <FrameLayout - android:id="@android:id/tabcontent" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <com.android.internal.app.ResolverViewPager - android:id="@+id/profile_pager" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - </FrameLayout> - </LinearLayout> - </TabHost> - - <LinearLayout - android:id="@+id/button_bar" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginVertical="@dimen/car_padding_4" - android:layout_marginHorizontal="@dimen/car_padding_4" - android:padding="0dp" - android:gravity="center" - android:background="@drawable/car_activity_resolver_list_background" - android:orientation="vertical"> - - <Button - android:id="@+id/button_once" - android:layout_width="match_parent" - android:layout_height="@dimen/car_button_height" - android:enabled="false" - android:layout_gravity="center" - android:layout_marginBottom="@dimen/car_padding_2" - android:text="@string/activity_resolver_use_once" - android:onClick="onButtonClick"/> - - <Button - android:id="@+id/button_always" - android:layout_width="match_parent" - android:layout_height="@dimen/car_button_height" - android:enabled="false" - android:layout_gravity="center" - android:text="@string/activity_resolver_use_always" - android:onClick="onButtonClick"/> - </LinearLayout> - - </LinearLayout> - -</com.android.internal.widget.ResolverDrawerLayout>
\ No newline at end of file diff --git a/core/res/res/layout-car/car_resolver_list_with_default.xml b/core/res/res/layout-car/car_resolver_list_with_default.xml deleted file mode 100644 index 08cc7ff3021f..000000000000 --- a/core/res/res/layout-car/car_resolver_list_with_default.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -* Copyright 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. -*/ ---> -<com.android.internal.widget.ResolverDrawerLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="@dimen/car_activity_resolver_width" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:id="@id/contentPanel"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_gravity="center" - android:background="@drawable/car_activity_resolver_list_background"> - - <FrameLayout - android:id="@+id/stub" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@drawable/car_activity_resolver_list_background"/> - - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="@dimen/car_activity_resolver_list_item_height" - android:orientation="horizontal"> - - <RadioButton - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:focusable="false" - android:clickable="false" - android:layout_marginStart="?attr/listPreferredItemPaddingStart" - android:layout_gravity="start|center_vertical" - android:checked="true"/> - - <ImageView - android:id="@+id/icon" - android:layout_width="@dimen/car_icon_size" - android:layout_height="@dimen/car_icon_size" - android:layout_gravity="start|center_vertical" - android:layout_marginStart="@dimen/car_padding_4" - android:src="@drawable/resolver_icon_placeholder" - android:scaleType="fitCenter"/> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginHorizontal="?attr/listPreferredItemPaddingStart" - style="?android:attr/textAppearanceListItem" - android:layout_gravity="start|center_vertical" /> - - <LinearLayout - android:id="@+id/profile_button" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/icon" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView - android:id="@id/text1" - android:visibility="gone" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - </LinearLayout> - </LinearLayout> - - <TabHost - android:id="@+id/profile_tabhost" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_centerHorizontal="true" - android:background="?attr/colorBackgroundFloating"> - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TabWidget - android:id="@android:id/tabs" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:visibility="gone"> - </TabWidget> - <View - android:id="@+id/resolver_tab_divider" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - <FrameLayout - android:id="@android:id/tabcontent" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <com.android.internal.app.ResolverViewPager - android:id="@+id/profile_pager" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - </com.android.internal.app.ResolverViewPager> - </FrameLayout> - </LinearLayout> - </TabHost> - - <LinearLayout - android:id="@+id/button_bar" - android:visibility="gone" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginVertical="@dimen/car_padding_4" - android:layout_marginHorizontal="@dimen/car_padding_4" - android:gravity="center" - android:background="@drawable/car_activity_resolver_list_background" - android:orientation="vertical"> - - <Button - android:id="@+id/button_once" - android:layout_width="match_parent" - android:layout_height="@dimen/car_button_height" - android:enabled="false" - android:layout_gravity="center" - android:layout_marginBottom="@dimen/car_padding_2" - android:text="@string/activity_resolver_use_once" - android:onClick="onButtonClick"/> - - <Button - android:id="@+id/button_always" - android:layout_width="match_parent" - android:layout_height="@dimen/car_button_height" - android:enabled="false" - android:layout_gravity="center" - android:text="@string/activity_resolver_use_always" - android:onClick="onButtonClick"/> - </LinearLayout> - </LinearLayout> - -</com.android.internal.widget.ResolverDrawerLayout> diff --git a/core/res/res/layout/input_method_switch_dialog_new.xml b/core/res/res/layout/input_method_switch_dialog_new.xml index 610a212bbd4e..058fe3fe3076 100644 --- a/core/res/res/layout/input_method_switch_dialog_new.xml +++ b/core/res/res/layout/input_method_switch_dialog_new.xml @@ -71,9 +71,10 @@ android:layout_height="wrap_content" android:background="@drawable/input_method_switch_button" android:layout_gravity="end" - android:text="@string/input_method_language_settings" + android:text="@string/input_method_switcher_settings_button" android:fontFamily="google-sans-text" android:textAppearance="?attr/textAppearance" + android:contentDescription="@string/input_method_language_settings" android:visibility="gone"/> </LinearLayout> diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml index 61c7a8cde7d5..383033d9ae5d 100644 --- a/core/res/res/values/config_telephony.xml +++ b/core/res/res/values/config_telephony.xml @@ -237,6 +237,13 @@ <integer name="config_emergency_call_wait_for_connection_timeout_millis">20000</integer> <java-symbol type="integer" name="config_emergency_call_wait_for_connection_timeout_millis" /> + <!-- The time duration in millis after which Telephony will stop waiting for the OFF state + from cellular modem, consider the request to power off cellular modem as failed, and thus + treat the cellular modem state as ON. + --> + <integer name="config_satellite_wait_for_cellular_modem_off_timeout_millis">120000</integer> + <java-symbol type="integer" name="config_satellite_wait_for_cellular_modem_off_timeout_millis" /> + <!-- Indicates the data limit in bytes that can be used for bootstrap sim until factory reset. -1 means unlimited. --> <integer name="config_esim_bootstrap_data_limit_bytes">-1</integer> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index cb58339f5ef3..f40466610724 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3280,6 +3280,9 @@ <!-- Accessibility text for the long click action on the switch input method button. This will be used following "Double-tap and hold to..." [CHAR LIMIT=NONE] --> <string name="input_method_ime_switch_long_click_action_desc">Open input method picker</string> + <!-- Button to access the language settings of the current input method + from the Input Method Switcher menu. [CHAR LIMIT=50]--> + <string name="input_method_switcher_settings_button">Settings</string> <!-- If the device is getting low on internal storage, a notification is shown to the user. This is the title of that notification. --> <string name="low_internal_storage_view_title">Storage space running out</string> @@ -3883,7 +3886,8 @@ <!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. --> <string name="select_input_method">Choose input method</string> - <!-- Button to access the language settings of the current input method. [CHAR LIMIT=50]--> + <!-- Content description of the button to access the language settings of the current input method + from the Input Method Switcher menu, for accessibility (not shown on the screen). [CHAR LIMIT=NONE]--> <string name="input_method_language_settings">Language Settings</string> <!-- Summary text of a toggle switch to enable/disable use of the IME while a physical keyboard is connected --> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index f5c67387cb92..452ae04c7199 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -212,30 +212,30 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> <item name="colorPopupBackground">?attr/colorBackgroundFloating</item> <item name="panelColorBackground">?attr/colorBackgroundFloating</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -314,28 +314,28 @@ easier. <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -431,28 +431,28 @@ easier. <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -550,28 +550,28 @@ easier. <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -668,28 +668,28 @@ easier. <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -801,28 +801,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -911,28 +911,28 @@ easier. <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1027,28 +1027,28 @@ easier. <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1144,28 +1144,28 @@ easier. <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1277,28 +1277,28 @@ easier. <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1395,28 +1395,28 @@ easier. <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1511,28 +1511,28 @@ easier. <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1629,28 +1629,28 @@ easier. <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1746,28 +1746,28 @@ easier. <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1863,28 +1863,28 @@ easier. <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -1980,28 +1980,28 @@ easier. <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -2097,28 +2097,28 @@ easier. <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -2218,28 +2218,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -2336,28 +2336,28 @@ easier. <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -2451,28 +2451,28 @@ easier. <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -2720,28 +2720,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> <item name="colorPopupBackground">?attr/colorBackgroundFloating</item> @@ -2821,28 +2821,28 @@ easier. <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_dark</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item> + <item name="colorPrimaryDark">@color/primary_device_default_dark</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -2937,28 +2937,28 @@ easier. <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3054,28 +3054,28 @@ easier. <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3173,28 +3173,28 @@ easier. <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3291,28 +3291,28 @@ easier. <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3426,28 +3426,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3535,28 +3535,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3654,28 +3654,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3774,28 +3774,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3895,26 +3895,26 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -3996,26 +3996,26 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4096,28 +4096,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4217,28 +4217,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4336,28 +4336,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4454,28 +4454,28 @@ easier. <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4571,28 +4571,28 @@ easier. <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4688,28 +4688,28 @@ easier. <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4803,28 +4803,28 @@ easier. <style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice"> <!-- Color palette --> <item name="colorPrimary">@color/primary_device_default_light</item> - <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item> + <item name="colorPrimaryDark">@color/primary_device_default_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -4932,21 +4932,21 @@ easier. <item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item> <!-- Color palette --> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorPrimary">@color/primary_device_default_settings_light</item> <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> <item name="colorSecondary">@color/secondary_device_default_settings_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> <item name="colorEdgeEffect">@color/edge_effect_device_default_light</item> @@ -5044,16 +5044,16 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> <item name="colorSecondary">@color/secondary_device_default_settings_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> <item name="colorControlNormal">?attr/textColorPrimary</item> <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item> @@ -5148,16 +5148,16 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> <item name="colorSecondary">@color/secondary_device_default_settings_light</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item> @@ -5245,26 +5245,26 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item> <item name="colorSecondary">@color/secondary_device_default_settings</item> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item> - <item name="colorSurface">@color/surface_dark</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item> - <item name="colorSurfaceVariant">@color/surface_variant_dark</item> - <item name="colorSurfaceHeader">@color/surface_header_dark</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item> + <item name="colorSurface">@color/system_surface_container_dark</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item> <item name="colorError">@color/error_color_device_default_dark</item> - <item name="colorBackground">@color/background_device_default_dark</item> + <item name="colorBackground">@color/system_surface_container_dark</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_dark</item> + <item name="textColorSecondary">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiary">@color/system_outline_dark</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_light</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item> + <item name="textColorTertiaryInverse">@color/system_outline_light</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_dark</item> <item name="colorForegroundInverse">@color/foreground_device_default_light</item> @@ -5361,26 +5361,26 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item> <item name="colorSecondary">@color/secondary_device_default_settings</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -5487,26 +5487,26 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item> <item name="colorSecondary">@color/secondary_device_default_settings</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -5606,26 +5606,26 @@ easier. <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item> <item name="colorSecondary">@color/secondary_device_default_settings</item> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> - <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item> - <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item> - <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item> - <item name="colorSurface">@color/surface_light</item> - <item name="colorSurfaceHighlight">@color/surface_highlight_light</item> - <item name="colorSurfaceVariant">@color/surface_variant_light</item> - <item name="colorSurfaceHeader">@color/surface_header_light</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> + <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item> + <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item> + <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item> + <item name="colorSurface">@color/system_surface_container_light</item> + <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item> + <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item> + <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item> <item name="colorError">@color/error_color_device_default_light</item> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item> - <item name="textColorPrimary">@color/text_color_primary_device_default_light</item> - <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item> - <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item> - <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item> - <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item> - <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item> - <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item> + <item name="textColorPrimary">@color/system_on_surface_light</item> + <item name="textColorSecondary">@color/system_on_surface_variant_light</item> + <item name="textColorTertiary">@color/system_outline_light</item> + <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item> + <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item> + <item name="textColorTertiaryInverse">@color/system_outline_dark</item> + <item name="textColorOnAccent">@color/system_on_primary_dark</item> <item name="colorForeground">@color/foreground_device_default_light</item> <item name="colorForegroundInverse">@color/foreground_device_default_dark</item> @@ -5788,9 +5788,9 @@ easier. <style name="ThemeOverlay.DeviceDefault.Accent"> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item> <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item> @@ -5863,9 +5863,9 @@ easier. <style name="ThemeOverlay.DeviceDefault.Accent.Light"> <item name="colorAccent">@color/accent_device_default_light</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item> <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item> @@ -5938,13 +5938,13 @@ easier. <!-- Theme overlay that replaces colorAccent with the colorAccent from {@link #Theme_DeviceDefault_DayNight}. --> <style name="ThemeOverlay.DeviceDefault.Accent.DayNight" - parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" /> + parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" /> <style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar"> <item name="colorAccent">@color/accent_device_default_dark</item> - <item name="colorAccentPrimary">@color/accent_primary_device_default</item> - <item name="colorAccentSecondary">@color/accent_secondary_device_default</item> - <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item> + <item name="colorAccentPrimary">@color/system_primary_dark</item> + <item name="colorAccentSecondary">@color/system_secondary_dark</item> + <item name="colorAccentTertiary">@color/system_tertiary_dark</item> <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item> <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item> @@ -6016,7 +6016,7 @@ easier. </style> <style name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" parent="Theme.DeviceDefault.NoActionBar.Fullscreen"> - <item name="colorBackground">@color/background_device_default_light</item> + <item name="colorBackground">@color/system_surface_container_light</item> <item name="colorBackgroundFloating">@color/background_device_default_light</item> <item name="layout_gravity">center</item> <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item> diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java index 832ebe534c67..6dad3b7b2ac4 100644 --- a/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java +++ b/core/tests/coretests/src/android/database/sqlite/SQLiteRawStatementTest.java @@ -999,4 +999,31 @@ public class SQLiteRawStatementTest { mDatabase.endTransaction(); } } + + /** + * This test verifies that the JNI exception thrown because of a bad column is actually thrown + * and does not crash the VM. + */ + @Test + public void testJniExceptions() { + // Create the t1 table. + mDatabase.beginTransaction(); + try { + mDatabase.execSQL("CREATE TABLE t1 (i int, j int);"); + mDatabase.setTransactionSuccessful(); + } finally { + mDatabase.endTransaction(); + } + + mDatabase.beginTransactionReadOnly(); + try (SQLiteRawStatement s = mDatabase.createRawStatement("SELECT * from t1")) { + s.step(); + s.getColumnText(5); // out-of-range column + fail("JNI exception not thrown"); + } catch (SQLiteBindOrColumnIndexOutOfRangeException e) { + // Passing case. + } finally { + mDatabase.endTransaction(); + } + } } diff --git a/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java new file mode 100644 index 000000000000..8a54e5b998e7 --- /dev/null +++ b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import static com.google.common.truth.Truth.assertThat; + +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.test.InstrumentationTestCase; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.text.flags.Flags; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * PaintTest tests {@link Paint}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class PaintFontVariationTest extends InstrumentationTestCase { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS) + @Test + public void testDerivedFromSameTypeface() { + final Paint p = new Paint(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 450")).isTrue(); + Typeface first = p.getTypeface(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 480")).isTrue(); + Typeface second = p.getTypeface(); + + assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom()); + } + + @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS) + @Test + public void testDerivedFromChained() { + final Paint p = new Paint(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 450")).isTrue(); + Typeface first = p.getTypeface(); + + assertThat(p.setFontVariationSettings("'wght' 480")).isTrue(); + Typeface second = p.getTypeface(); + + assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom()); + } +} diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java index 0dec756d7611..878ba703c8fe 100644 --- a/core/tests/coretests/src/android/graphics/PaintTest.java +++ b/core/tests/coretests/src/android/graphics/PaintTest.java @@ -16,13 +16,22 @@ package android.graphics; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertNotEquals; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.test.InstrumentationTestCase; import android.text.TextUtils; import androidx.test.filters.SmallTest; +import com.android.text.flags.Flags; + +import org.junit.Rule; + import java.util.Arrays; import java.util.HashSet; @@ -30,6 +39,9 @@ import java.util.HashSet; * PaintTest tests {@link Paint}. */ public class PaintTest extends InstrumentationTestCase { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + private static final String FONT_PATH = "fonts/HintedAdvanceWidthTest-Regular.ttf"; static void assertEquals(String message, float[] expected, float[] actual) { @@ -403,4 +415,33 @@ public class PaintTest extends InstrumentationTestCase { assertEquals(6, getClusterCount(p, rtlStr + ltrStr)); assertEquals(9, getClusterCount(p, ltrStr + rtlStr + ltrStr)); } + + @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS) + public void testDerivedFromSameTypeface() { + final Paint p = new Paint(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 450")).isTrue(); + Typeface first = p.getTypeface(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 480")).isTrue(); + Typeface second = p.getTypeface(); + + assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom()); + } + + @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS) + public void testDerivedFromChained() { + final Paint p = new Paint(); + + p.setTypeface(Typeface.SANS_SERIF); + assertThat(p.setFontVariationSettings("'wght' 450")).isTrue(); + Typeface first = p.getTypeface(); + + assertThat(p.setFontVariationSettings("'wght' 480")).isTrue(); + Typeface second = p.getTypeface(); + + assertThat(first.getDerivedFrom()).isSameInstanceAs(second.getDerivedFrom()); + } } diff --git a/core/tests/coretests/src/android/os/VibrationAttributesTest.java b/core/tests/coretests/src/android/os/VibrationAttributesTest.java index d8142c8d91bf..5bdae0e6455b 100644 --- a/core/tests/coretests/src/android/os/VibrationAttributesTest.java +++ b/core/tests/coretests/src/android/os/VibrationAttributesTest.java @@ -28,11 +28,9 @@ public class VibrationAttributesTest { @Test public void testSimple() throws Exception { final VibrationAttributes attr = new VibrationAttributes.Builder() - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .setUsage(VibrationAttributes.USAGE_ALARM) .build(); - assertEquals(VibrationAttributes.CATEGORY_KEYBOARD, attr.getCategory()); assertEquals(VibrationAttributes.USAGE_ALARM, attr.getUsage()); } } diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java index b8ff59528b24..c631c6f46e37 100644 --- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java +++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java @@ -994,6 +994,35 @@ public class ViewFrameRateTest { mViewRoot.getLastPreferredFrameRateCategory()); } + /** + * If a View is an instance of ViewGroupOverlay, + * we obtain the velocity from its hostView. + */ + @Test + @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API) + public void overlayViewGroupVelocity() throws Throwable { + if (!ViewProperties.vrr_enabled().orElse(true)) { + return; + } + + FrameLayout host = new FrameLayout(mActivity); + View childView = new View(mActivity); + float velocity = 1000; + + mActivityRule.runOnUiThread(() -> { + ViewGroup.LayoutParams fullSize = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + mActivity.setContentView(host, fullSize); + host.setFrameContentVelocity(velocity); + ViewGroupOverlay overlay = host.getOverlay(); + overlay.add(childView); + assertEquals(velocity, host.getFrameContentVelocity()); + assertEquals(host.getFrameContentVelocity(), + ((View) childView.getParent()).getFrameContentVelocity()); + }); + } + private void runAfterDraw(@NonNull Runnable runnable) { Handler handler = new Handler(Looper.getMainLooper()); mAfterDrawLatch = new CountDownLatch(1); diff --git a/core/tests/coretests/src/android/view/contentprotection/OWNERS b/core/tests/coretests/src/android/view/contentprotection/OWNERS index b3583a7f6ab1..3d09da303b0f 100644 --- a/core/tests/coretests/src/android/view/contentprotection/OWNERS +++ b/core/tests/coretests/src/android/view/contentprotection/OWNERS @@ -1,4 +1,4 @@ -# Bug component: 544200 +# Bug component: 1040349 -include /core/java/android/view/contentcapture/OWNERS +include /core/java/android/view/contentprotection/OWNERS diff --git a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java index f9da832ba7de..b11307e0393d 100644 --- a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java +++ b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java @@ -23,7 +23,9 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyChar; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -251,8 +253,9 @@ public class TextViewContextMenuTest { when(menu.add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt())) .thenReturn(mockAutofillMenuItem); - EditText et = mActivity.findViewById(R.id.editText); - et.setText("Test"); + EditText et = spy(mActivity.findViewById(R.id.editText)); + doReturn(true).when(et).canRequestAutofill(); + doReturn(null).when(et).getSelectedText(); Editor editor = et.getEditorForTesting(); editor.onCreateContextMenu(menu); @@ -271,11 +274,11 @@ public class TextViewContextMenuTest { when(menu.add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt())) .thenReturn(mockAutofillMenuItem); - EditText et = mActivity.findViewById(R.id.editText); - et.setText("Test"); - et.selectAll(); - Editor editor = et.getEditorForTesting(); - editor.onCreateContextMenu(menu); + EditText et = spy(mActivity.findViewById(R.id.editText)); + doReturn(true).when(et).canRequestAutofill(); + doReturn("test").when(et).getSelectedText(); + Editor editor = new Editor(et); + editor.setTextContextMenuItems(menu); verify(menu).add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt()); verify(mockAutofillMenuItem).setEnabled(false); diff --git a/core/tests/coretests/src/com/android/internal/util/RateLimitingCacheTest.java b/core/tests/coretests/src/com/android/internal/util/RateLimitingCacheTest.java new file mode 100644 index 000000000000..7541a844c1da --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/util/RateLimitingCacheTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.os.SystemClock; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test the RateLimitingCache class. + */ +@RunWith(AndroidJUnit4.class) +public class RateLimitingCacheTest { + + private int mCounter = 0; + + @Before + public void before() { + mCounter = -1; + } + + RateLimitingCache.ValueFetcher<Integer> mFetcher = () -> { + return ++mCounter; + }; + + /** + * Test zero period passed into RateLimitingCache. A new value should be returned for each + * time the cache's get() is invoked. + */ + @Test + public void testTtl_Zero() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(0); + + int first = s.get(mFetcher); + assertEquals(first, 0); + int second = s.get(mFetcher); + assertEquals(second, 1); + SystemClock.sleep(20); + int third = s.get(mFetcher); + assertEquals(third, 2); + } + + /** + * Test a period of 100ms passed into RateLimitingCache. A new value should not be fetched + * any more frequently than every 100ms. + */ + @Test + public void testTtl_100() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(100); + + int first = s.get(mFetcher); + assertEquals(first, 0); + int second = s.get(mFetcher); + // Too early to change + assertEquals(second, 0); + SystemClock.sleep(150); + int third = s.get(mFetcher); + // Changed by now + assertEquals(third, 1); + int fourth = s.get(mFetcher); + // Too early to change again + assertEquals(fourth, 1); + } + + /** + * Test a negative period passed into RateLimitingCache. A new value should only be fetched the + * first call to get(). + */ + @Test + public void testTtl_Negative() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(-1); + + int first = s.get(mFetcher); + assertEquals(first, 0); + SystemClock.sleep(200); + // Should return the original value every time + int second = s.get(mFetcher); + assertEquals(second, 0); + } + + /** + * Test making tons of calls to the speed-limiter and make sure number of fetches does not + * exceed expected number of fetches. + */ + @Test + public void testTtl_Spam() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(100); + assertCount(s, 1000, 7, 15); + } + + /** + * Test rate-limiting across multiple periods and make sure the expected number of fetches is + * within the specified rate. + */ + @Test + public void testRate_10hz() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(1000, 10); + // At 10 per second, 2 seconds should not exceed about 30, assuming overlap into left and + // right windows that allow 10 each + assertCount(s, 2000, 20, 33); + } + + /** + * Test that using a different timebase works correctly. + */ + @Test + public void testTimebase() { + RateLimitingCache<Integer> s = new RateLimitingCache<>(1000, 10) { + @Override + protected long getTime() { + return SystemClock.elapsedRealtime() / 2; + } + }; + // Timebase is moving at half the speed, so only allows for 1 second worth in 2 seconds. + assertCount(s, 2000, 10, 22); + } + + /** + * Helper to make repeated calls every 5 millis to verify the number of expected fetches for + * the given parameters. + * @param cache the cache object + * @param period the period for which to make get() calls + * @param minCount the lower end of the expected number of fetches, with a margin for error + * @param maxCount the higher end of the expected number of fetches, with a margin for error + */ + private void assertCount(RateLimitingCache<Integer> cache, long period, + int minCount, int maxCount) { + long startTime = SystemClock.elapsedRealtime(); + while (SystemClock.elapsedRealtime() < startTime + period) { + int value = cache.get(mFetcher); + SystemClock.sleep(5); + } + int latest = cache.get(mFetcher); + assertTrue("Latest should be between " + minCount + " and " + maxCount + + " but is " + latest, latest <= maxCount && latest >= minCount); + } +} diff --git a/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java b/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java index c1e357864fff..471b4021545a 100644 --- a/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java +++ b/core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java @@ -68,6 +68,16 @@ public class ResourceFlaggingTest { assertThat(getBoolean("res3")).isTrue(); } + @Test + public void testFlagDisabledStringArrayElement() { + assertThat(getStringArray("strarr1")).isEqualTo(new String[]{"one", "two", "three"}); + } + + @Test + public void testFlagDisabledIntArrayElement() { + assertThat(getIntArray("intarr1")).isEqualTo(new int[]{1, 2, 3}); + } + private boolean getBoolean(String name) { int resId = mResources.getIdentifier( name, @@ -77,13 +87,22 @@ public class ResourceFlaggingTest { return mResources.getBoolean(resId); } - private String getString(String name) { + private String[] getStringArray(String name) { + int resId = mResources.getIdentifier( + name, + "array", + "com.android.intenal.flaggedresources"); + assertThat(resId).isNotEqualTo(0); + return mResources.getStringArray(resId); + } + + private int[] getIntArray(String name) { int resId = mResources.getIdentifier( name, - "string", + "array", "com.android.intenal.flaggedresources"); assertThat(resId).isNotEqualTo(0); - return mResources.getString(resId); + return mResources.getIntArray(resId); } private String extractApkAndGetPath(int id) throws Exception { diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java index bd3d94467ead..4f76dd636c30 100644 --- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java +++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java @@ -60,7 +60,7 @@ import java.util.Arrays; @RunWith(MockitoJUnitRunner.class) public class VibrationEffectTest { - + private static final float TOLERANCE = 1e-2f; private static final String RINGTONE_URI_1 = "content://test/system/ringtone_1"; private static final String RINGTONE_URI_2 = "content://test/system/ringtone_2"; private static final String RINGTONE_URI_3 = "content://test/system/ringtone_3"; @@ -709,7 +709,7 @@ public class VibrationEffectTest { @Test public void testScaleWaveform() { VibrationEffect scaledUp = TEST_WAVEFORM.scale(1.5f); - assertEquals(1f, getStepSegment(scaledUp, 0).getAmplitude(), 1e-5f); + assertEquals(1f, getStepSegment(scaledUp, 0).getAmplitude(), TOLERANCE); VibrationEffect scaledDown = TEST_WAVEFORM.scale(0.5f); assertTrue(1f > getStepSegment(scaledDown, 0).getAmplitude()); @@ -731,11 +731,11 @@ public class VibrationEffectTest { public void testScaleVendorEffect() { VibrationEffect effect = VibrationEffect.createVendorEffect(createNonEmptyBundle()); - VibrationEffect scaledUp = effect.scale(1.5f); - assertEquals(effect, scaledUp); + VibrationEffect.VendorEffect scaledUp = (VibrationEffect.VendorEffect) effect.scale(1.5f); + assertEquals(1.5f, scaledUp.getScale()); - VibrationEffect scaledDown = effect.scale(0.5f); - assertEquals(effect, scaledDown); + VibrationEffect.VendorEffect scaledDown = (VibrationEffect.VendorEffect) effect.scale(0.5f); + assertEquals(0.5f, scaledDown.getScale()); } @Test @@ -755,6 +755,70 @@ public class VibrationEffectTest { } @Test + public void testApplyAdaptiveScaleOneShot() { + VibrationEffect oneShot = VibrationEffect.createOneShot(TEST_TIMING, /* amplitude= */ 100); + + VibrationEffect scaledUp = oneShot.applyAdaptiveScale(1.5f); + assertThat(getStepSegment(scaledUp, 0).getAmplitude()).isWithin(TOLERANCE).of(150 / 255f); + + VibrationEffect scaledDown = oneShot.applyAdaptiveScale(0.5f); + assertThat(getStepSegment(scaledDown, 0).getAmplitude()).isWithin(TOLERANCE).of(50 / 255f); + } + + @Test + public void testApplyAdaptiveScaleWaveform() { + VibrationEffect waveform = VibrationEffect.createWaveform( + new long[] { 100, 100 }, new int[] { 10, 0 }, -1); + + VibrationEffect scaledUp = waveform.applyAdaptiveScale(1.5f); + assertThat(getStepSegment(scaledUp, 0).getAmplitude()).isWithin(TOLERANCE).of(15 / 255f); + + VibrationEffect scaledDown = waveform.applyAdaptiveScale(0.5f); + assertThat(getStepSegment(scaledDown, 0).getAmplitude()).isWithin(TOLERANCE).of(5 / 255f); + } + + @Test + public void testApplyAdaptiveScalePrebaked() { + VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); + + VibrationEffect scaledUp = effect.applyAdaptiveScale(1.5f); + assertEquals(effect, scaledUp); + + VibrationEffect scaledDown = effect.applyAdaptiveScale(0.5f); + assertEquals(effect, scaledDown); + } + + @Test + @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) + public void testApplyAdaptiveScaleVendorEffect() { + VibrationEffect effect = VibrationEffect.createVendorEffect(createNonEmptyBundle()); + + VibrationEffect.VendorEffect scaledUp = + (VibrationEffect.VendorEffect) effect.applyAdaptiveScale(1.5f); + assertEquals(1.5f, scaledUp.getAdaptiveScale()); + + VibrationEffect.VendorEffect scaledDown = + (VibrationEffect.VendorEffect) effect.applyAdaptiveScale(0.5f); + assertEquals(0.5f, scaledDown.getAdaptiveScale()); + } + + @Test + public void testApplyAdaptiveScaleComposed() { + VibrationEffect effect = VibrationEffect.startComposition() + .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 1) + .addEffect(VibrationEffect.createOneShot(TEST_TIMING, /* amplitude= */ 100)) + .compose(); + + VibrationEffect scaledUp = effect.applyAdaptiveScale(1.5f); + assertThat(getPrimitiveSegment(scaledUp, 0).getScale()).isWithin(TOLERANCE).of(0.75f); + assertThat(getStepSegment(scaledUp, 1).getAmplitude()).isWithin(TOLERANCE).of(150 / 255f); + + VibrationEffect scaledDown = effect.applyAdaptiveScale(0.5f); + assertThat(getPrimitiveSegment(scaledDown, 0).getScale()).isWithin(TOLERANCE).of(0.25f); + assertThat(getStepSegment(scaledDown, 1).getAmplitude()).isWithin(TOLERANCE).of(50 / 255f); + } + + @Test public void testApplyEffectStrengthToOneShotWaveformAndPrimitives() { VibrationEffect oneShot = VibrationEffect.createOneShot(100, 100); VibrationEffect waveform = VibrationEffect.createWaveform(new long[] { 10, 20 }, 0); diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index fd788167a0d8..889a778556b7 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -56,6 +56,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.text.flags.Flags; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -74,6 +75,7 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -143,6 +145,23 @@ public class Typeface { private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16); private static final Object sDynamicCacheLock = new Object(); + private static final LruCache<Long, LruCache<String, Typeface>> sVariableCache = + new LruCache<>(16); + private static final Object sVariableCacheLock = new Object(); + + /** @hide */ + @VisibleForTesting + public static void clearTypefaceCachesForTestingPurpose() { + synchronized (sWeightCacheLock) { + sWeightTypefaceCache.clear(); + } + synchronized (sDynamicCacheLock) { + sDynamicTypefaceCache.evictAll(); + } + synchronized (sVariableCacheLock) { + sVariableCache.evictAll(); + } + } @GuardedBy("SYSTEM_FONT_MAP_LOCK") static Typeface sDefaultTypeface; @@ -195,6 +214,8 @@ public class Typeface { @UnsupportedAppUsage public final long native_instance; + private final Typeface mDerivedFrom; + private final String mSystemFontFamilyName; private final Runnable mCleaner; @@ -274,6 +295,18 @@ public class Typeface { } /** + * Returns the Typeface used for creating this Typeface. + * + * Maybe null if this is not derived from other Typeface. + * TODO(b/357707916): Make this public API. + * @hide + */ + @VisibleForTesting + public final @Nullable Typeface getDerivedFrom() { + return mDerivedFrom; + } + + /** * Returns the system font family name if the typeface was created from a system font family, * otherwise returns null. */ @@ -1021,9 +1054,51 @@ public class Typeface { return typeface; } - /** @hide */ + private static String axesToVarKey(@NonNull List<FontVariationAxis> axes) { + // The given list can be mutated because it is allocated in Paint#setFontVariationSettings. + // Currently, Paint#setFontVariationSettings is the only code path reaches this method. + axes.sort(Comparator.comparingInt(FontVariationAxis::getOpenTypeTagValue)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < axes.size(); ++i) { + final FontVariationAxis fva = axes.get(i); + sb.append(fva.getTag()); + sb.append(fva.getStyleValue()); + } + return sb.toString(); + } + + /** + * TODO(b/357707916): Make this public API. + * @hide + */ public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family, @NonNull List<FontVariationAxis> axes) { + if (Flags.typefaceCacheForVarSettings()) { + final Typeface target = (family == null) ? Typeface.DEFAULT : family; + final Typeface base = (target.mDerivedFrom == null) ? target : target.mDerivedFrom; + + final String key = axesToVarKey(axes); + + synchronized (sVariableCacheLock) { + LruCache<String, Typeface> innerCache = sVariableCache.get(base.native_instance); + if (innerCache == null) { + // Cache up to 16 var instance per root Typeface + innerCache = new LruCache<>(16); + sVariableCache.put(base.native_instance, innerCache); + } else { + Typeface cached = innerCache.get(key); + if (cached != null) { + return cached; + } + } + Typeface typeface = new Typeface( + nativeCreateFromTypefaceWithVariation(base.native_instance, axes), + base.getSystemFontFamilyName(), base); + innerCache.put(key, typeface); + return typeface; + } + } + final Typeface base = family == null ? Typeface.DEFAULT : family; Typeface typeface = new Typeface( nativeCreateFromTypefaceWithVariation(base.native_instance, axes), @@ -1184,11 +1259,19 @@ public class Typeface { // don't allow clients to call this directly @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private Typeface(long ni) { - this(ni, null); + this(ni, null, null); } + // don't allow clients to call this directly + // This is kept for robolectric. private Typeface(long ni, @Nullable String systemFontFamilyName) { + this(ni, systemFontFamilyName, null); + } + + // don't allow clients to call this directly + private Typeface(long ni, @Nullable String systemFontFamilyName, + @Nullable Typeface derivedFrom) { if (ni == 0) { throw new RuntimeException("native typeface cannot be made"); } @@ -1198,6 +1281,7 @@ public class Typeface { mStyle = nativeGetStyle(ni); mWeight = nativeGetWeight(ni); mSystemFontFamilyName = systemFontFamilyName; + mDerivedFrom = derivedFrom; } /** diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java new file mode 100644 index 000000000000..69a68c85a2fe --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.window.extensions.embedding; + +import android.os.Build; +import android.os.Bundle; +import android.os.Looper; +import android.os.MessageQueue; +import android.util.Log; + +import androidx.annotation.NonNull; + +import java.util.List; + +/** + * Helper class to back up and restore the TaskFragmentOrganizer state, in order to resume + * organizing the TaskFragments if the app process is restarted. + */ +@SuppressWarnings("GuardedBy") +class BackupHelper { + private static final String TAG = "BackupHelper"; + private static final boolean DEBUG = Build.isDebuggable(); + + private static final String KEY_TASK_CONTAINERS = "KEY_TASK_CONTAINERS"; + @NonNull + private final SplitController mController; + @NonNull + private final BackupIdler mBackupIdler = new BackupIdler(); + private boolean mBackupIdlerScheduled; + + BackupHelper(@NonNull SplitController splitController, @NonNull Bundle savedState) { + mController = splitController; + + if (!savedState.isEmpty()) { + restoreState(savedState); + } + } + + /** + * Schedules a back-up request. It is no-op if there was a request scheduled and not yet + * completed. + */ + void scheduleBackup() { + if (!mBackupIdlerScheduled) { + mBackupIdlerScheduled = true; + Looper.myQueue().addIdleHandler(mBackupIdler); + } + } + + final class BackupIdler implements MessageQueue.IdleHandler { + @Override + public boolean queueIdle() { + synchronized (mController.mLock) { + mBackupIdlerScheduled = false; + startBackup(); + } + return false; + } + } + + private void startBackup() { + final List<TaskContainer> taskContainers = mController.getTaskContainers(); + if (taskContainers.isEmpty()) { + Log.w(TAG, "No task-container to back up"); + return; + } + + if (DEBUG) Log.d(TAG, "Start to back up " + taskContainers); + final Bundle state = new Bundle(); + state.setClassLoader(TaskContainer.class.getClassLoader()); + state.putParcelableList(KEY_TASK_CONTAINERS, taskContainers); + mController.setSavedState(state); + } + + private void restoreState(@NonNull Bundle savedState) { + if (savedState.isEmpty()) { + return; + } + + final List<TaskContainer> taskContainers = savedState.getParcelableArrayList( + KEY_TASK_CONTAINERS, TaskContainer.class); + for (TaskContainer taskContainer : taskContainers) { + if (DEBUG) Log.d(TAG, "restore task " + taskContainer.getTaskId()); + // TODO(b/289875940): implement the TaskContainer restoration. + } + } +} 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 26d180cdcb1a..bb384c5d0e84 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -2536,6 +2536,21 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return mTaskContainers.get(taskId); } + @NonNull + @GuardedBy("mLock") + List<TaskContainer> getTaskContainers() { + final ArrayList<TaskContainer> taskContainers = new ArrayList<>(); + for (int i = mTaskContainers.size() - 1; i >= 0; i--) { + taskContainers.add(mTaskContainers.valueAt(i)); + } + return taskContainers; + } + + @GuardedBy("mLock") + void setSavedState(@NonNull Bundle savedState) { + mPresenter.setSavedState(savedState); + } + @GuardedBy("mLock") void addTaskContainer(int taskId, TaskContainer taskContainer) { mTaskContainers.put(taskId, taskContainer); @@ -2829,6 +2844,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return getActiveSplitForContainer(container) != null; } + void scheduleBackup() { + synchronized (mLock) { + mPresenter.scheduleBackup(); + } + } + private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @Override diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index 99716e7cc69e..fb8efc4ad490 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -158,6 +158,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { private final WindowLayoutComponentImpl mWindowLayoutComponent; private final SplitController mController; + @NonNull + private final BackupHelper mBackupHelper; SplitPresenter(@NonNull Executor executor, @NonNull WindowLayoutComponentImpl windowLayoutComponent, @@ -165,7 +167,18 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { super(executor, controller); mWindowLayoutComponent = windowLayoutComponent; mController = controller; - registerOrganizer(); + final Bundle outSavedState = new Bundle(); + if (Flags.aeBackStackRestore()) { + outSavedState.setClassLoader(TaskContainer.class.getClassLoader()); + registerOrganizer(false /* isSystemOrganizer */, outSavedState); + } else { + registerOrganizer(); + } + mBackupHelper = new BackupHelper(controller, outSavedState); + } + + void scheduleBackup() { + mBackupHelper.scheduleBackup(); } /** diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java index 20ad53ee19a8..5795e8da18c2 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java @@ -32,6 +32,8 @@ import android.app.WindowConfiguration.WindowingMode; import android.content.res.Configuration; import android.graphics.Rect; import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Log; @@ -48,12 +50,14 @@ import androidx.window.extensions.embedding.SplitAttributes.SplitType; import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType; import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType; +import com.android.window.flags.Flags; + import java.util.ArrayList; import java.util.List; import java.util.Set; /** Represents TaskFragments and split pairs below a Task. */ -class TaskContainer { +class TaskContainer implements Parcelable { private static final String TAG = TaskContainer.class.getSimpleName(); /** The unique task id. */ @@ -80,6 +84,9 @@ class TaskContainer { @NonNull private TaskFragmentParentInfo mInfo; + @NonNull + private SplitController mSplitController; + /** * TaskFragments that the organizer has requested to be closed. They should be removed when * the organizer receives @@ -116,12 +123,14 @@ class TaskContainer { /** * The {@link TaskContainer} constructor * - * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with - * {@code activityInTask}. - * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to - * initialize the {@link TaskContainer} properties. + * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with + * {@code activityInTask}. + * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to + * initialize the {@link TaskContainer} properties. + * @param splitController The {@link SplitController}. */ - TaskContainer(int taskId, @NonNull Activity activityInTask) { + TaskContainer(int taskId, @NonNull Activity activityInTask, + @Nullable SplitController splitController) { if (taskId == INVALID_TASK_ID) { throw new IllegalArgumentException("Invalid Task id"); } @@ -136,6 +145,7 @@ class TaskContainer { true /* visible */, true /* hasDirectActivity */, null /* decorSurface */); + mSplitController = splitController; } int getTaskId() { @@ -571,6 +581,12 @@ class TaskContainer { // Update overlay container after split pin container since the overlay should be on top of // pin container. updateAlwaysOnTopOverlayIfNecessary(); + + // TODO(b/289875940): Making backup-restore as an opt-in solution, before the flag goes + // to next-food. + if (Flags.aeBackStackRestore()) { + mSplitController.scheduleBackup(); + } } private void updateAlwaysOnTopOverlayIfNecessary() { @@ -664,6 +680,34 @@ class TaskContainer { return activityStacks; } + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mTaskId); + // TODO(b/289875940) + } + + protected TaskContainer(Parcel in) { + mTaskId = in.readInt(); + // TODO(b/289875940) + } + + public static final Creator<TaskContainer> CREATOR = new Creator<>() { + @Override + public TaskContainer createFromParcel(Parcel in) { + return new TaskContainer(in); + } + + @Override + public TaskContainer[] newArray(int size) { + return new TaskContainer[size]; + } + }; + /** A wrapper class which contains the information of {@link TaskContainer} */ static final class TaskProperties { private final int mDisplayId; 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 ee3e6f368505..dc6506b070af 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -1203,7 +1203,7 @@ class TaskFragmentContainer { if (taskContainer == null) { // Adding a TaskContainer if no existed one. - taskContainer = new TaskContainer(mTaskId, mActivityInTask); + taskContainer = new TaskContainer(mTaskId, mActivityInTask, mSplitController); mSplitController.addTaskContainer(mTaskId, taskContainer); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarImpl.java index 60bc7bedf2ed..a1de2062e906 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package androidx.window.sidecar; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.Application; @@ -23,8 +24,9 @@ import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.IBinder; +import android.util.ArraySet; +import android.util.Log; -import androidx.annotation.NonNull; import androidx.window.common.BaseDataProducer; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; import androidx.window.common.EmptyLifecycleCallbacksAdapter; @@ -33,17 +35,27 @@ import androidx.window.common.layout.CommonFoldingFeature; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.Set; /** - * Reference implementation of androidx.window.sidecar OEM interface for use with - * WindowManager Jetpack. + * Basic implementation of the {@link SidecarInterface}. An OEM can choose to use it as the base + * class for their implementation. */ -class SampleSidecarImpl extends StubSidecar { +class SidecarImpl implements SidecarInterface { + + private static final String TAG = "WindowManagerSidecar"; + + @Nullable + private SidecarCallback mSidecarCallback; + private final ArraySet<IBinder> mWindowLayoutChangeListenerTokens = new ArraySet<>(); + private boolean mDeviceStateChangeListenerRegistered; + @NonNull private List<CommonFoldingFeature> mStoredFeatures = new ArrayList<>(); - SampleSidecarImpl(Context context) { + SidecarImpl(Context context) { ((Application) context.getApplicationContext()) - .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); + .registerActivityLifecycleCallbacks(new SidecarImpl.NotifyOnConfigurationChanged()); RawFoldingFeatureProducer settingsFeatureProducer = new RawFoldingFeatureProducer(context); BaseDataProducer<List<CommonFoldingFeature>> foldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context, @@ -53,11 +65,46 @@ class SampleSidecarImpl extends StubSidecar { foldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } - private void setStoredFeatures(List<CommonFoldingFeature> storedFeatures) { - mStoredFeatures = storedFeatures; + @NonNull + @Override + public SidecarDeviceState getDeviceState() { + return SidecarHelper.calculateDeviceState(mStoredFeatures); + } + + @NonNull + @Override + public SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) { + return SidecarHelper.calculateWindowLayoutInfo(windowToken, mStoredFeatures); + } + + @Override + public void setSidecarCallback(@NonNull SidecarCallback sidecarCallback) { + mSidecarCallback = sidecarCallback; + } + + @Override + public void onWindowLayoutChangeListenerAdded(@NonNull IBinder iBinder) { + mWindowLayoutChangeListenerTokens.add(iBinder); + onListenersChanged(); + } + + @Override + public void onWindowLayoutChangeListenerRemoved(@NonNull IBinder iBinder) { + mWindowLayoutChangeListenerTokens.remove(iBinder); + onListenersChanged(); + } + + @Override + public void onDeviceStateListenersChanged(boolean isEmpty) { + mDeviceStateChangeListenerRegistered = !isEmpty; + onListenersChanged(); + } + + private void setStoredFeatures(@NonNull List<CommonFoldingFeature> storedFeatures) { + mStoredFeatures = Objects.requireNonNull(storedFeatures); } - private void onDisplayFeaturesChanged(List<CommonFoldingFeature> storedFeatures) { + private void onDisplayFeaturesChanged(@NonNull List<CommonFoldingFeature> storedFeatures) { setStoredFeatures(storedFeatures); updateDeviceState(getDeviceState()); for (IBinder windowToken : getWindowsListeningForLayoutChanges()) { @@ -66,25 +113,43 @@ class SampleSidecarImpl extends StubSidecar { } } - @NonNull - @Override - public SidecarDeviceState getDeviceState() { - return SidecarHelper.calculateDeviceState(mStoredFeatures); + void updateDeviceState(@NonNull SidecarDeviceState newState) { + if (mSidecarCallback != null) { + try { + mSidecarCallback.onDeviceStateChanged(newState); + } catch (AbstractMethodError e) { + Log.e(TAG, "App is using an outdated Window Jetpack library", e); + } + } + } + + void updateWindowLayout(@NonNull IBinder windowToken, + @NonNull SidecarWindowLayoutInfo newLayout) { + if (mSidecarCallback != null) { + try { + mSidecarCallback.onWindowLayoutChanged(windowToken, newLayout); + } catch (AbstractMethodError e) { + Log.e(TAG, "App is using an outdated Window Jetpack library", e); + } + } } @NonNull - @Override - public SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken) { - return SidecarHelper.calculateWindowLayoutInfo(windowToken, mStoredFeatures); + private Set<IBinder> getWindowsListeningForLayoutChanges() { + return mWindowLayoutChangeListenerTokens; } - @Override - protected void onListenersChanged() { + protected boolean hasListeners() { + return !mWindowLayoutChangeListenerTokens.isEmpty() || mDeviceStateChangeListenerRegistered; + } + + private void onListenersChanged() { if (hasListeners()) { onDisplayFeaturesChanged(mStoredFeatures); } } + private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter { @Override public void onActivityCreated(@NonNull Activity activity, diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarProvider.java index 686a31b6be04..1e306fcebda0 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarProvider.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SidecarProvider.java @@ -36,7 +36,7 @@ public class SidecarProvider { @Nullable public static SidecarInterface getSidecarImpl(Context context) { return isWindowExtensionsEnabled() - ? new SampleSidecarImpl(context.getApplicationContext()) + ? new SidecarImpl(context.getApplicationContext()) : null; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java deleted file mode 100644 index 46c1f3ba4691..000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java +++ /dev/null @@ -1,96 +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 androidx.window.sidecar; - -import android.os.IBinder; -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.util.HashSet; -import java.util.Set; - -/** - * Basic implementation of the {@link SidecarInterface}. An OEM can choose to use it as the base - * class for their implementation. - */ -abstract class StubSidecar implements SidecarInterface { - - private static final String TAG = "WindowManagerSidecar"; - - private SidecarCallback mSidecarCallback; - final Set<IBinder> mWindowLayoutChangeListenerTokens = new HashSet<>(); - private boolean mDeviceStateChangeListenerRegistered; - - StubSidecar() { - } - - @Override - public void setSidecarCallback(@NonNull SidecarCallback sidecarCallback) { - this.mSidecarCallback = sidecarCallback; - } - - @Override - public void onWindowLayoutChangeListenerAdded(@NonNull IBinder iBinder) { - this.mWindowLayoutChangeListenerTokens.add(iBinder); - this.onListenersChanged(); - } - - @Override - public void onWindowLayoutChangeListenerRemoved(@NonNull IBinder iBinder) { - this.mWindowLayoutChangeListenerTokens.remove(iBinder); - this.onListenersChanged(); - } - - @Override - public void onDeviceStateListenersChanged(boolean isEmpty) { - this.mDeviceStateChangeListenerRegistered = !isEmpty; - this.onListenersChanged(); - } - - void updateDeviceState(SidecarDeviceState newState) { - if (this.mSidecarCallback != null) { - try { - mSidecarCallback.onDeviceStateChanged(newState); - } catch (AbstractMethodError e) { - Log.e(TAG, "App is using an outdated Window Jetpack library", e); - } - } - } - - void updateWindowLayout(@NonNull IBinder windowToken, - @NonNull SidecarWindowLayoutInfo newLayout) { - if (this.mSidecarCallback != null) { - try { - mSidecarCallback.onWindowLayoutChanged(windowToken, newLayout); - } catch (AbstractMethodError e) { - Log.e(TAG, "App is using an outdated Window Jetpack library", e); - } - } - } - - @NonNull - Set<IBinder> getWindowsListeningForLayoutChanges() { - return mWindowLayoutChangeListenerTokens; - } - - protected boolean hasListeners() { - return !mWindowLayoutChangeListenerTokens.isEmpty() || mDeviceStateChangeListenerRegistered; - } - - protected abstract void onListenersChanged(); -} diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java index 7dc78fdd601f..5c85778ee42d 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java @@ -222,7 +222,7 @@ public class EmbeddingTestUtils { doReturn(resources).when(activity).getResources(); doReturn(DEFAULT_DISPLAY).when(activity).getDisplayId(); - return new TaskContainer(TASK_ID, activity); + return new TaskContainer(TASK_ID, activity, mock(SplitController.class)); } static TaskContainer createTestTaskContainer(@NonNull SplitController controller) { diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index 1c3d9c30c91c..1a3aa8eec5ec 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -44,18 +44,10 @@ filegroup { filegroup { name: "wm_shell_util-sources", srcs: [ - "src/com/android/wm/shell/animation/Interpolators.java", "src/com/android/wm/shell/common/bubbles/*.kt", "src/com/android/wm/shell/common/bubbles/*.java", - "src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt", - "src/com/android/wm/shell/common/split/SplitScreenConstants.java", - "src/com/android/wm/shell/common/TransactionPool.java", - "src/com/android/wm/shell/common/TriangleShape.java", "src/com/android/wm/shell/common/desktopmode/*.kt", - "src/com/android/wm/shell/draganddrop/DragAndDropConstants.java", "src/com/android/wm/shell/pip/PipContentOverlay.java", - "src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java", - "src/com/android/wm/shell/sysui/ShellSharedConstants.java", "src/com/android/wm/shell/util/**/*.java", ], path: "src", diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig index 56ea7c201e53..9de10c0619da 100644 --- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig +++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig @@ -128,3 +128,13 @@ flag { description: "Enable bubble bar to be shown in the persistent task bar" bug: "346391377" } + +flag { + name: "bubble_view_info_executors" + namespace: "multitasking" + description: "Use executors to inflate bubble views" + bug: "353894869" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt index ae60d8bc2596..4b97451a0c41 100644 --- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt @@ -268,7 +268,8 @@ class BubblePositionerTest { ) positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) assertThat(positioner.getExpandedViewHeight(bubble)).isEqualTo(MAX_HEIGHT) } @@ -294,6 +295,7 @@ class BubblePositionerTest { 0 /* taskId */, null /* locus */, true /* isDismissable */, + directExecutor(), directExecutor() ) {} @@ -322,6 +324,7 @@ class BubblePositionerTest { 0 /* taskId */, null /* locus */, true /* isDismissable */, + directExecutor(), directExecutor() ) {} @@ -416,7 +419,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) // This bubble will have max height so it'll always be top aligned assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */)) @@ -433,7 +437,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) // Always top aligned in phone portrait assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */)) @@ -452,7 +457,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) // This bubble will have max height which is always top aligned on small tablets assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */)) @@ -470,7 +476,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) // This bubble will have max height which is always top aligned on small tablets assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */)) @@ -489,7 +496,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) // This bubble will have max height which is always top aligned on landscape, large tablet assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */)) @@ -507,7 +515,8 @@ class BubblePositionerTest { positioner.update(deviceConfig) val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) val manageButtonHeight = context.resources.getDimensionPixelSize(R.dimen.bubble_manage_button_height) diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt index 84f7bb27ca82..faadf1d623c9 100644 --- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt @@ -102,6 +102,7 @@ class BubbleStackViewTest { BubbleLogger(UiEventLoggerFake()), positioner, BubbleEducationController(context), + shellExecutor, shellExecutor ) bubbleStackViewManager = FakeBubbleStackViewManager() @@ -364,6 +365,7 @@ class BubbleStackViewTest { /* taskId= */ 0, "locus", /* isDismissable= */ true, + directExecutor(), directExecutor() ) {} inflateBubble(bubble) @@ -373,7 +375,8 @@ class BubbleStackViewTest { private fun createAndInflateBubble(): Bubble { val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName) val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button) - val bubble = Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor()) + val bubble = + Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor(), directExecutor()) inflateBubble(bubble) return bubble } diff --git a/libs/WindowManager/Shell/res/drawable/decor_maximize_button_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_maximize_button_dark.xml index ab4e29ac97e5..7b3353462bd6 100644 --- a/libs/WindowManager/Shell/res/drawable/decor_maximize_button_dark.xml +++ b/libs/WindowManager/Shell/res/drawable/decor_maximize_button_dark.xml @@ -17,19 +17,16 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="32.0dp" android:height="32.0dp" - android:viewportWidth="32.0" - android:viewportHeight="32.0" - android:tint="@color/decor_button_dark_color"> + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <group android:scaleX="0.5" android:scaleY="0.5" - android:translateX="8.0" - android:translateY="8.0" > + android:translateX="6.0" + android:translateY="6.0" > <path - android:fillColor="@android:color/white" - android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/> - <path - android:fillColor="@android:color/white" - android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/> + android:fillColor="@android:color/black" + android:fillType="evenOdd" + android:pathData="M23.0,1.0v22.0H1V1h22zm-3,19H4V4h16v16z"/> </group> </vector> diff --git a/libs/WindowManager/Shell/res/drawable/decor_restore_button_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_restore_button_dark.xml new file mode 100644 index 000000000000..91c8f544c08d --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/decor_restore_button_dark.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <group android:scaleX="0.5" + android:scaleY="0.5" + android:translateX="6.0" + android:translateY="6.0" > + <path + android:fillColor="@android:color/black" + android:fillType="evenOdd" + android:pathData="M23,16H8V1h15v15zm-12,-3V4h9v9h-9zM4,8H1v15h15v-3H4V8z"/> + </group> +</vector> diff --git a/libs/WindowManager/Shell/res/layout/compat_ui_restart_button_layout.xml b/libs/WindowManager/Shell/res/layout/compat_ui_restart_button_layout.xml new file mode 100644 index 000000000000..d00c69cb2993 --- /dev/null +++ b/libs/WindowManager/Shell/res/layout/compat_ui_restart_button_layout.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="bottom|end"> + + <include android:id="@+id/size_compat_hint" + android:visibility="gone" + android:layout_width="@dimen/compat_hint_width" + android:layout_height="wrap_content" + layout="@layout/compat_mode_hint"/> + + <ImageButton + android:id="@+id/size_compat_restart_button" + android:visibility="gone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/compat_button_margin" + android:layout_marginBottom="@dimen/compat_button_margin" + android:src="@drawable/size_compat_restart_button_ripple" + android:background="@android:color/transparent" + android:contentDescription="@string/restart_button_description"/> + +</LinearLayout> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index 8627c0b920e5..53ab2d56f6e6 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -539,20 +539,23 @@ <!-- The size of the icon shown in the resize veil. --> <dimen name="desktop_mode_resize_veil_icon_size">96dp</dimen> - <!-- The with of the border around the app task for edge resizing, when + <!-- The width of the border outside the app task eligible for edge resizing, when enable_windowing_edge_drag_resize is enabled. --> - <dimen name="desktop_mode_edge_handle">12dp</dimen> + <dimen name="freeform_edge_handle_outset">10dp</dimen> + + <!-- The size of the border inside the app task eligible for edge resizing, when + enable_windowing_edge_drag_resize is enabled. --> + <dimen name="freeform_edge_handle_inset">2dp</dimen> <!-- The original width of the border around the app task for edge resizing, when enable_windowing_edge_drag_resize is disabled. --> <dimen name="freeform_resize_handle">15dp</dimen> <!-- The size of the corner region for drag resizing with touch, when a larger touch region is - appropriate. Applied when enable_windowing_edge_drag_resize is enabled. --> + appropriate. --> <dimen name="desktop_mode_corner_resize_large">48dp</dimen> - <!-- The original size of the corner region for darg resizing, when - enable_windowing_edge_drag_resize is disabled. --> + <!-- The size of the corner region for drag resizing with a cursor or a stylus. --> <dimen name="freeform_resize_corner">44dp</dimen> <!-- The thickness in dp for all desktop drag transition regions. --> diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index 6a62d7a373c8..36d0a3c63b03 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -302,4 +302,6 @@ <string name="desktop_mode_maximize_menu_maximize_text">Maximize Screen</string> <!-- Maximize menu snap buttons string. --> <string name="desktop_mode_maximize_menu_snap_text">Snap Screen</string> + <!-- Snap resizing non-resizable string. --> + <string name="desktop_mode_non_resizable_snap_text">This app can\'t be resized</string> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellSharedConstants.java index c886cc999216..8f7a2e5a6789 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellSharedConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.sysui; +package com.android.wm.shell.shared; /** * General shell-related constants that are shared with users of the library. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TransactionPool.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransactionPool.java index 4c34566b0d98..0c5d88dc44a8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TransactionPool.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransactionPool.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.common; +package com.android.wm.shell.shared; import android.util.Pools; import android.view.SurfaceControl; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TriangleShape.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TriangleShape.java index 707919033065..0ca53278acbb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TriangleShape.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TriangleShape.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.common; +package com.android.wm.shell.shared; import android.graphics.Outline; import android.graphics.Path; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java index ce0bf8b29374..f45dc3a1e892 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/animation/Interpolators.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.animation; +package com.android.wm.shell.shared.animation; import android.graphics.Path; import android.view.animation.BackGestureInterpolator; diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java index 282385a16b5f..341ca0eb6bed 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java @@ -24,6 +24,8 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; +import java.io.PrintWriter; + /** * Constants for desktop mode feature */ @@ -203,4 +205,19 @@ public class DesktopModeStatus { private static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) { return !enforceDeviceRestrictions() || isDesktopModeSupported(context); } + + /** Dumps DesktopModeStatus flags and configs. */ + public static void dump(PrintWriter pw, String prefix, Context context) { + String innerPrefix = prefix + " "; + pw.print(prefix); pw.println(TAG); + pw.print(innerPrefix); pw.print("maxTaskLimit="); pw.println(getMaxTaskLimit(context)); + + pw.print(innerPrefix); pw.print("maxTaskLimit config override="); + pw.println(context.getResources().getInteger( + R.integer.config_maxDesktopWindowingActiveTasks)); + + SystemProperties.Handle maxTaskLimitHandle = SystemProperties.find(MAX_TASK_LIMIT_SYS_PROP); + pw.print(innerPrefix); pw.print("maxTaskLimit sysprop="); + pw.println(maxTaskLimitHandle == null ? "null" : maxTaskLimitHandle.getInt(/* def= */ -1)); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/draganddrop/DragAndDropConstants.java index 20da54efd286..4127adc1f901 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/draganddrop/DragAndDropConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.draganddrop; +package com.android.wm.shell.shared.draganddrop; /** Constants that can be used by both Shell and other users of the library, e.g. Launcher */ public class DragAndDropConstants { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/magnetictarget/MagnetizedObject.kt index 123d4dc49199..efdc6f8cd9de 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/magnetictarget/MagnetizedObject.kt +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/magnetictarget/MagnetizedObject.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.wm.shell.common.magnetictarget + +package com.android.wm.shell.shared.magnetictarget import android.annotation.SuppressLint import android.content.Context diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java index 8c06de79ba76..498dc8bdd24d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.wm.shell.common.split; +package com.android.wm.shell.shared.split; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -30,7 +30,7 @@ public class SplitScreenConstants { /** Duration used for every split fade-in or fade-out. */ public static final int FADE_DURATION = 133; /** Duration where we keep an app veiled to allow it to redraw itself behind the scenes. */ - public static final int VEIL_DELAY_DURATION = 400; + public static final int VEIL_DELAY_DURATION = 300; /** Key for passing in widget intents when invoking split from launcher workspace. */ public static final String KEY_EXTRA_WIDGET_INTENT = "key_extra_widget_intent"; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/startingsurface/SplashScreenExitAnimationUtils.java index ea8c0eb30061..da9bf7a2cba0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/startingsurface/SplashScreenExitAnimationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.wm.shell.startingsurface; +package com.android.wm.shell.shared.startingsurface; import static android.view.Choreographer.CALLBACK_COMMIT; @@ -45,8 +45,8 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.window.SplashScreenView; -import com.android.wm.shell.animation.Interpolators; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; +import com.android.wm.shell.shared.animation.Interpolators; /** * Utilities for creating the splash screen window animations. @@ -88,7 +88,7 @@ public class SplashScreenExitAnimationUtils { * Creates and starts the animator to fade out the icon, reveal the app, and shift up main * window with rounded corner radius. */ - static void startAnimations(@ExitAnimationType int animationType, + public static void startAnimations(@ExitAnimationType int animationType, ViewGroup splashScreenView, SurfaceControl firstWindowSurface, int mainWindowShiftLength, TransactionPool transactionPool, Rect firstWindowFrame, int animationDuration, int iconFadeOutDuration, float iconStartAlpha, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java index 26edd7d2268b..be1f71e939be 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java @@ -23,6 +23,8 @@ import android.view.ViewPropertyAnimator; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; +import com.android.wm.shell.shared.animation.Interpolators; + import javax.inject.Inject; /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java index d754d04e6b33..26f7b360e0fc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java @@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Color; import android.graphics.Rect; import android.view.SurfaceControl; @@ -59,6 +60,23 @@ public class BackAnimationBackground { */ public void ensureBackground(Rect startRect, int color, @NonNull SurfaceControl.Transaction transaction, int statusbarHeight) { + ensureBackground(startRect, color, transaction, statusbarHeight, + null /* cropBounds */, 0 /* cornerRadius */); + } + + /** + * Ensures the back animation background color layer is present. + * + * @param startRect The start bounds of the closing target. + * @param color The background color. + * @param transaction The animation transaction. + * @param statusbarHeight The height of the statusbar (in px). + * @param cropBounds The crop bounds of the surface, set to non-empty to show wallpaper. + * @param cornerRadius The radius of corner, only work when cropBounds is not empty. + */ + public void ensureBackground(Rect startRect, int color, + @NonNull SurfaceControl.Transaction transaction, int statusbarHeight, + @Nullable Rect cropBounds, float cornerRadius) { if (mBackgroundSurface != null) { return; } @@ -78,6 +96,10 @@ public class BackAnimationBackground { transaction.setColor(mBackgroundSurface, colorComponents) .setLayer(mBackgroundSurface, BACKGROUND_LAYER) .show(mBackgroundSurface); + if (cropBounds != null && !cropBounds.isEmpty()) { + transaction.setCrop(mBackgroundSurface, cropBounds) + .setCornerRadius(mBackgroundSurface, cornerRadius); + } mStartBounds = startRect; mIsRequestingStatusBarAppearance = false; mStatusbarHeight = statusbarHeight; 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 12422874ca5d..d7da0515f228 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 @@ -29,7 +29,7 @@ import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BA import static com.android.window.flags.Flags.migratePredictiveBackTransition; import static com.android.window.flags.Flags.predictiveBackSystemAnims; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION; import android.annotation.NonNull; import android.annotation.Nullable; @@ -146,7 +146,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private final Handler mBgHandler; private final WindowManager mWindowManager; private final Transitions mTransitions; - private final BackTransitionHandler mBackTransitionHandler; + @VisibleForTesting + final BackTransitionHandler mBackTransitionHandler; @VisibleForTesting final Rect mTouchableArea = new Rect(); @@ -174,7 +175,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @Nullable private IOnBackInvokedCallback mActiveCallback; @Nullable - private RemoteAnimationTarget[] mApps; + @VisibleForTesting + RemoteAnimationTarget[] mApps; @VisibleForTesting final RemoteCallback mNavigationObserver = new RemoteCallback( @@ -1311,15 +1313,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont info.getChanges().remove(j); } } - tmpSize = info.getChanges().size(); - for (int i = 0; i < tmpSize; ++i) { - final TransitionInfo.Change change = init.getChanges().get(i); - if (moveToTop) { - if (isSameChangeTarget(openComponent, openTaskId, change)) { - change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); + // Ignore merge if there is no close target + if (!info.getChanges().isEmpty()) { + tmpSize = init.getChanges().size(); + for (int i = 0; i < tmpSize; ++i) { + final TransitionInfo.Change change = init.getChanges().get(i); + if (moveToTop) { + if (isSameChangeTarget(openComponent, openTaskId, change)) { + change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); + } } + info.getChanges().add(i, change); } - info.getChanges().add(i, change); } } else { // Open transition, the transition info should be: @@ -1448,7 +1453,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont * Check whether this transition is prepare for predictive back animation, which could * happen when core make an activity become visible. */ - private boolean handlePrepareTransition( + @VisibleForTesting + boolean handlePrepareTransition( @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction st, @NonNull SurfaceControl.Transaction ft, @@ -1491,7 +1497,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont * Check whether this transition is triggered from back gesture commitment. * Reparent the transition targets to animation leashes, so the animation won't be broken. */ - private boolean handleCloseTransition(@NonNull TransitionInfo info, + @VisibleForTesting + boolean handleCloseTransition(@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction st, @NonNull SurfaceControl.Transaction ft, @NonNull Transitions.TransitionFinishCallback finishCallback) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt index c7e8df980a8b..32e809a23a91 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt @@ -51,8 +51,8 @@ import com.android.internal.policy.SystemBarUtils import com.android.internal.protolog.ProtoLog import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer -import com.android.wm.shell.animation.Interpolators import com.android.wm.shell.protolog.ShellProtoLogGroup +import com.android.wm.shell.shared.animation.Interpolators import kotlin.math.abs import kotlin.math.max import kotlin.math.min @@ -189,10 +189,13 @@ abstract class CrossActivityBackAnimation( preparePreCommitEnteringRectMovement() background.ensureBackground( - closingTarget!!.windowConfiguration.bounds, - getBackgroundColor(), - transaction, - statusbarHeight + closingTarget!!.windowConfiguration.bounds, + getBackgroundColor(), + transaction, + statusbarHeight, + if (closingTarget!!.windowConfiguration.tasksAreFloating()) + closingTarget!!.localBounds else null, + cornerRadius ) ensureScrimLayer() if (isLetterboxed && enteringHasSameLetterbox) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java index e2b0513c951f..3fccecab4319 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java @@ -51,7 +51,7 @@ import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.shared.animation.Interpolators; import javax.inject.Inject; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt index c747e1e98956..66d8a5f2eeb9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt @@ -20,7 +20,7 @@ import android.view.SurfaceControl import android.window.BackEvent import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import javax.inject.Inject import kotlin.math.max diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java index dc511be59764..c1dadada505a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java @@ -37,7 +37,7 @@ import androidx.constraintlayout.widget.ConstraintLayout; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconNormalizer; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.shared.animation.Interpolators; import java.util.EnumSet; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 5cd2cb7d51d5..021d3c32fd63 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -54,6 +54,8 @@ import com.android.wm.shell.Flags; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.bubbles.BubbleInfo; +import com.android.wm.shell.shared.annotations.ShellBackgroundThread; +import com.android.wm.shell.shared.annotations.ShellMainThread; import java.io.PrintWriter; import java.util.List; @@ -79,6 +81,7 @@ public class Bubble implements BubbleViewProvider { private final LocusId mLocusId; private final Executor mMainExecutor; + private final Executor mBgExecutor; private long mLastUpdated; private long mLastAccessed; @@ -111,7 +114,10 @@ public class Bubble implements BubbleViewProvider { @Nullable private BubbleTaskView mBubbleTaskView; + @Nullable private BubbleViewInfoTask mInflationTask; + @Nullable + private BubbleViewInfoTaskLegacy mInflationTaskLegacy; private boolean mInflateSynchronously; private boolean mPendingIntentCanceled; private boolean mIsImportantConversation; @@ -203,7 +209,9 @@ public class Bubble implements BubbleViewProvider { @VisibleForTesting(visibility = PRIVATE) public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo, final int desiredHeight, final int desiredHeightResId, @Nullable final String title, - int taskId, @Nullable final String locus, boolean isDismissable, Executor mainExecutor, + int taskId, @Nullable final String locus, boolean isDismissable, + @ShellMainThread Executor mainExecutor, + @ShellBackgroundThread Executor bgExecutor, final Bubbles.BubbleMetadataFlagListener listener) { Objects.requireNonNull(key); Objects.requireNonNull(shortcutInfo); @@ -222,6 +230,7 @@ public class Bubble implements BubbleViewProvider { mTitle = title; mShowBubbleUpdateDot = false; mMainExecutor = mainExecutor; + mBgExecutor = bgExecutor; mTaskId = taskId; mBubbleMetadataFlagListener = listener; mIsAppBubble = false; @@ -233,7 +242,8 @@ public class Bubble implements BubbleViewProvider { @Nullable Icon icon, boolean isAppBubble, String key, - Executor mainExecutor) { + @ShellMainThread Executor mainExecutor, + @ShellBackgroundThread Executor bgExecutor) { mGroupKey = null; mLocusId = null; mFlags = 0; @@ -243,13 +253,15 @@ public class Bubble implements BubbleViewProvider { mKey = key; mShowBubbleUpdateDot = false; mMainExecutor = mainExecutor; + mBgExecutor = bgExecutor; mTaskId = INVALID_TASK_ID; mAppIntent = intent; mDesiredHeight = Integer.MAX_VALUE; mPackageName = intent.getPackage(); } - private Bubble(ShortcutInfo info, Executor mainExecutor) { + private Bubble(ShortcutInfo info, @ShellMainThread Executor mainExecutor, + @ShellBackgroundThread Executor bgExecutor) { mGroupKey = null; mLocusId = null; mFlags = 0; @@ -259,6 +271,7 @@ public class Bubble implements BubbleViewProvider { mKey = getBubbleKeyForShortcut(info); mShowBubbleUpdateDot = false; mMainExecutor = mainExecutor; + mBgExecutor = bgExecutor; mTaskId = INVALID_TASK_ID; mAppIntent = null; mDesiredHeight = Integer.MAX_VALUE; @@ -267,24 +280,21 @@ public class Bubble implements BubbleViewProvider { } /** Creates an app bubble. */ - public static Bubble createAppBubble( - Intent intent, - UserHandle user, - @Nullable Icon icon, - Executor mainExecutor) { + public static Bubble createAppBubble(Intent intent, UserHandle user, @Nullable Icon icon, + @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) { return new Bubble(intent, user, icon, /* isAppBubble= */ true, /* key= */ getAppBubbleKeyForApp(intent.getPackage(), user), - mainExecutor); + mainExecutor, bgExecutor); } /** Creates a shortcut bubble. */ public static Bubble createShortcutBubble( ShortcutInfo info, - Executor mainExecutor) { - return new Bubble(info, mainExecutor); + @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) { + return new Bubble(info, mainExecutor, bgExecutor); } /** @@ -309,7 +319,7 @@ public class Bubble implements BubbleViewProvider { public Bubble(@NonNull final BubbleEntry entry, final Bubbles.BubbleMetadataFlagListener listener, final Bubbles.PendingIntentCanceledListener intentCancelListener, - Executor mainExecutor) { + @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) { mIsAppBubble = false; mKey = entry.getKey(); mGroupKey = entry.getGroupKey(); @@ -324,6 +334,7 @@ public class Bubble implements BubbleViewProvider { }); }; mMainExecutor = mainExecutor; + mBgExecutor = bgExecutor; mTaskId = INVALID_TASK_ID; setEntry(entry); } @@ -557,40 +568,70 @@ public class Bubble implements BubbleViewProvider { @Nullable BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean skipInflation) { - if (isBubbleLoading()) { - mInflationTask.cancel(true /* mayInterruptIfRunning */); - } - mInflationTask = new BubbleViewInfoTask(this, - context, - expandedViewManager, - taskViewFactory, - positioner, - stackView, - layerView, - iconFactory, - skipInflation, - callback, - mMainExecutor); - if (mInflateSynchronously) { - mInflationTask.onPostExecute(mInflationTask.doInBackground()); + if (Flags.bubbleViewInfoExecutors()) { + if (mInflationTask != null && mInflationTask.getStatus() != FINISHED) { + mInflationTask.cancel(true /* mayInterruptIfRunning */); + } + // TODO(b/353894869): switch to executors + mInflationTask = new BubbleViewInfoTask(this, + context, + expandedViewManager, + taskViewFactory, + positioner, + stackView, + layerView, + iconFactory, + skipInflation, + callback, + mMainExecutor); + if (mInflateSynchronously) { + mInflationTask.onPostExecute(mInflationTask.doInBackground()); + } else { + mInflationTask.execute(); + } } else { - mInflationTask.execute(); + if (mInflationTaskLegacy != null && mInflationTaskLegacy.getStatus() != FINISHED) { + mInflationTaskLegacy.cancel(true /* mayInterruptIfRunning */); + } + mInflationTaskLegacy = new BubbleViewInfoTaskLegacy(this, + context, + expandedViewManager, + taskViewFactory, + positioner, + stackView, + layerView, + iconFactory, + skipInflation, + bubble -> { + if (callback != null) { + callback.onBubbleViewsReady(bubble); + } + }, + mMainExecutor); + if (mInflateSynchronously) { + mInflationTaskLegacy.onPostExecute(mInflationTaskLegacy.doInBackground()); + } else { + mInflationTaskLegacy.execute(); + } } } - private boolean isBubbleLoading() { - return mInflationTask != null && mInflationTask.getStatus() != FINISHED; - } - boolean isInflated() { return (mIconView != null && mExpandedView != null) || mBubbleBarExpandedView != null; } void stopInflation() { - if (mInflationTask == null) { - return; + if (Flags.bubbleViewInfoExecutors()) { + if (mInflationTask == null) { + return; + } + mInflationTask.cancel(true /* mayInterruptIfRunning */); + } else { + if (mInflationTaskLegacy == null) { + return; + } + mInflationTaskLegacy.cancel(true /* mayInterruptIfRunning */); } - mInflationTask.cancel(true /* mayInterruptIfRunning */); } void setViewInfo(BubbleViewInfoTask.BubbleViewInfo info) { @@ -626,6 +667,42 @@ public class Bubble implements BubbleViewProvider { } /** + * @deprecated {@link BubbleViewInfoTaskLegacy} is deprecated. + */ + @Deprecated + void setViewInfoLegacy(BubbleViewInfoTaskLegacy.BubbleViewInfo info) { + if (!isInflated()) { + mIconView = info.imageView; + mExpandedView = info.expandedView; + mBubbleBarExpandedView = info.bubbleBarExpandedView; + } + + mShortcutInfo = info.shortcutInfo; + mAppName = info.appName; + if (mTitle == null) { + mTitle = mAppName; + } + mFlyoutMessage = info.flyoutMessage; + + mBadgeBitmap = info.badgeBitmap; + mRawBadgeBitmap = info.rawBadgeBitmap; + mBubbleBitmap = info.bubbleBitmap; + + mDotColor = info.dotColor; + mDotPath = info.dotPath; + + if (mExpandedView != null) { + mExpandedView.update(this /* bubble */); + } + if (mBubbleBarExpandedView != null) { + mBubbleBarExpandedView.update(this /* bubble */); + } + if (mIconView != null) { + mIconView.setRenderedBubble(this /* bubble */); + } + } + + /** * Set visibility of bubble in the expanded state. * * <p>Note that this contents visibility doesn't affect visibility at {@link android.view.View}, 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 29520efd70b0..dabfeebf5cce 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 @@ -35,7 +35,7 @@ import static com.android.wm.shell.bubbles.Bubbles.DISMISS_PACKAGE_REMOVED; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_SHORTCUT_REMOVED; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_CHANGED; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES; import android.annotation.BinderThread; import android.annotation.NonNull; @@ -1495,7 +1495,7 @@ public class BubbleController implements ConfigurationChangeListener, b.setAppBubbleIntent(intent); } else { // App bubble does not exist, lets add and expand it - b = Bubble.createAppBubble(intent, user, icon, mMainExecutor); + b = Bubble.createAppBubble(intent, user, icon, mMainExecutor, mBackgroundExecutor); } ProtoLog.d(WM_SHELL_BUBBLES, "inflateAndAdd %s", appBubbleKey); b.setShouldAutoExpand(true); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index 3c6c6fa0d8d5..4ad1802cba7f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -43,6 +43,8 @@ import com.android.wm.shell.R; import com.android.wm.shell.bubbles.Bubbles.DismissReason; import com.android.wm.shell.common.bubbles.BubbleBarUpdate; import com.android.wm.shell.common.bubbles.RemovedBubble; +import com.android.wm.shell.shared.annotations.ShellBackgroundThread; +import com.android.wm.shell.shared.annotations.ShellMainThread; import java.io.PrintWriter; import java.util.ArrayList; @@ -201,6 +203,7 @@ public class BubbleData { private final BubblePositioner mPositioner; private final BubbleEducationController mEducationController; private final Executor mMainExecutor; + private final Executor mBgExecutor; /** Bubbles that are actively in the stack. */ private final List<Bubble> mBubbles; /** Bubbles that aged out to overflow. */ @@ -246,12 +249,14 @@ public class BubbleData { private HashMap<String, String> mSuppressedGroupKeys = new HashMap<>(); public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner, - BubbleEducationController educationController, Executor mainExecutor) { + BubbleEducationController educationController, @ShellMainThread Executor mainExecutor, + @ShellBackgroundThread Executor bgExecutor) { mContext = context; mLogger = bubbleLogger; mPositioner = positioner; mEducationController = educationController; mMainExecutor = mainExecutor; + mBgExecutor = bgExecutor; mOverflow = new BubbleOverflow(context, positioner); mBubbles = new ArrayList<>(); mOverflowBubbles = new ArrayList<>(); @@ -431,7 +436,8 @@ public class BubbleData { bubbleToReturn = new Bubble(entry, mBubbleMetadataFlagListener, mCancelledListener, - mMainExecutor); + mMainExecutor, + mBgExecutor); } else { // If there's no entry it must be a persisted bubble bubbleToReturn = persistedBubble; @@ -450,7 +456,7 @@ public class BubbleData { String bubbleKey = Bubble.getBubbleKeyForShortcut(info); Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey); if (bubbleToReturn == null) { - bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor); + bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor, mBgExecutor); } return bubbleToReturn; } @@ -461,7 +467,7 @@ public class BubbleData { user); Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey); if (bubbleToReturn == null) { - bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor); + bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor, mBgExecutor); } return bubbleToReturn; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt index df12999afc9d..818ba45bec42 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt @@ -31,6 +31,9 @@ import com.android.wm.shell.bubbles.storage.BubbleEntity import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository import com.android.wm.shell.common.ShellExecutor +import com.android.wm.shell.shared.annotations.ShellBackgroundThread +import com.android.wm.shell.shared.annotations.ShellMainThread +import java.util.concurrent.Executor import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -41,7 +44,8 @@ import kotlinx.coroutines.yield class BubbleDataRepository( private val launcherApps: LauncherApps, - private val mainExecutor: ShellExecutor, + @ShellMainThread private val mainExecutor: ShellExecutor, + @ShellBackgroundThread private val bgExecutor: Executor, private val persistentRepository: BubblePersistentRepository, ) { private val volatileRepository = BubbleVolatileRepository(launcherApps) @@ -259,8 +263,8 @@ class BubbleDataRepository( entity.locus, entity.isDismissable, mainExecutor, - bubbleMetadataFlagListener - ) + bgExecutor, + bubbleMetadataFlagListener) } } mainExecutor.execute { cb(bubbles) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index c9fcd5886787..52955267a501 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -71,7 +71,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.Flags; import com.android.wm.shell.R; import com.android.wm.shell.common.AlphaOptimizedButton; -import com.android.wm.shell.common.TriangleShape; +import com.android.wm.shell.shared.TriangleShape; import com.android.wm.shell.taskview.TaskView; import java.io.PrintWriter; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java index 42de401d9db9..1711dca4a8a3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java @@ -19,8 +19,8 @@ package com.android.wm.shell.bubbles; import static android.graphics.Paint.ANTI_ALIAS_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; -import static com.android.wm.shell.animation.Interpolators.ALPHA_IN; -import static com.android.wm.shell.animation.Interpolators.ALPHA_OUT; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_IN; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_OUT; import android.animation.ArgbEvaluator; import android.content.Context; @@ -50,7 +50,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; import com.android.wm.shell.R; -import com.android.wm.shell.common.TriangleShape; +import com.android.wm.shell.shared.TriangleShape; /** * Flyout view that appears as a 'chat bubble' alongside the bubble stack. The flyout can visually diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 322b01e3e033..53bbf888df5a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -19,8 +19,6 @@ package com.android.wm.shell.bubbles; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static com.android.wm.shell.animation.Interpolators.ALPHA_IN; -import static com.android.wm.shell.animation.Interpolators.ALPHA_OUT; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.wm.shell.bubbles.BubblePositioner.NUM_VISIBLE_WHEN_RESTING; @@ -28,6 +26,8 @@ import static com.android.wm.shell.bubbles.BubblePositioner.StackPinnedEdge.LEFT import static com.android.wm.shell.bubbles.BubblePositioner.StackPinnedEdge.RIGHT; import static com.android.wm.shell.common.bubbles.BubbleConstants.BUBBLE_EXPANDED_SCRIM_ALPHA; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_IN; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_OUT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -82,7 +82,6 @@ import com.android.internal.protolog.ProtoLog; import com.android.internal.util.FrameworkStatsLog; import com.android.wm.shell.Flags; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.bubbles.BubblesNavBarMotionEventHandler.MotionEventListener; import com.android.wm.shell.bubbles.animation.AnimatableScaleMatrix; import com.android.wm.shell.bubbles.animation.ExpandedAnimationController; @@ -94,8 +93,9 @@ import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.bubbles.DismissView; import com.android.wm.shell.common.bubbles.RelativeTouchListener; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import java.io.PrintWriter; import java.math.BigDecimal; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index 69119cf4338e..03a2efd902f9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -54,6 +54,7 @@ import java.util.concurrent.Executor; /** * Simple task to inflate views & load necessary info to display a bubble. */ +// TODO(b/353894869): switch to executors public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask.BubbleViewInfo> { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleViewInfoTask" : TAG_BUBBLES; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java new file mode 100644 index 000000000000..5cfebf8f1647 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java @@ -0,0 +1,346 @@ +/* + * 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.bubbles; + +import static com.android.wm.shell.bubbles.BadgedImageView.DEFAULT_PATH_SIZE; +import static com.android.wm.shell.bubbles.BadgedImageView.WHITE_SCRIM_ALPHA; +import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; +import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ShortcutInfo; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Path; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.os.AsyncTask; +import android.util.Log; +import android.util.PathParser; +import android.view.LayoutInflater; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.ColorUtils; +import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.BubbleIconFactory; +import com.android.wm.shell.R; +import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; +import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; + +import java.lang.ref.WeakReference; +import java.util.Objects; +import java.util.concurrent.Executor; + +/** + * Simple task to inflate views & load necessary info to display a bubble. + * + * @deprecated Deprecated since this is using an AsyncTask. Use {@link BubbleViewInfoTask} instead. + */ +@Deprecated +// TODO(b/353894869): remove once flag for loading view info with executors rolls out +public class BubbleViewInfoTaskLegacy extends + AsyncTask<Void, Void, BubbleViewInfoTaskLegacy.BubbleViewInfo> { + private static final String TAG = + TAG_WITH_CLASS_NAME ? "BubbleViewInfoTaskLegacy" : TAG_BUBBLES; + + + /** + * Callback to find out when the bubble has been inflated & necessary data loaded. + */ + public interface Callback { + /** + * Called when data has been loaded for the bubble. + */ + void onBubbleViewsReady(Bubble bubble); + } + + private Bubble mBubble; + private WeakReference<Context> mContext; + private WeakReference<BubbleExpandedViewManager> mExpandedViewManager; + private WeakReference<BubbleTaskViewFactory> mTaskViewFactory; + private WeakReference<BubblePositioner> mPositioner; + private WeakReference<BubbleStackView> mStackView; + private WeakReference<BubbleBarLayerView> mLayerView; + private BubbleIconFactory mIconFactory; + private boolean mSkipInflation; + private Callback mCallback; + private Executor mMainExecutor; + + /** + * Creates a task to load information for the provided {@link Bubble}. Once all info + * is loaded, {@link Callback} is notified. + */ + BubbleViewInfoTaskLegacy(Bubble b, + Context context, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, + @Nullable BubbleStackView stackView, + @Nullable BubbleBarLayerView layerView, + BubbleIconFactory factory, + boolean skipInflation, + Callback c, + Executor mainExecutor) { + mBubble = b; + mContext = new WeakReference<>(context); + mExpandedViewManager = new WeakReference<>(expandedViewManager); + mTaskViewFactory = new WeakReference<>(taskViewFactory); + mPositioner = new WeakReference<>(positioner); + mStackView = new WeakReference<>(stackView); + mLayerView = new WeakReference<>(layerView); + mIconFactory = factory; + mSkipInflation = skipInflation; + mCallback = c; + mMainExecutor = mainExecutor; + } + + @Override + protected BubbleViewInfo doInBackground(Void... voids) { + if (!verifyState()) { + // If we're in an inconsistent state, then switched modes and should just bail now. + return null; + } + if (mLayerView.get() != null) { + return BubbleViewInfo.populateForBubbleBar(mContext.get(), mExpandedViewManager.get(), + mTaskViewFactory.get(), mPositioner.get(), mLayerView.get(), mIconFactory, + mBubble, mSkipInflation); + } else { + return BubbleViewInfo.populate(mContext.get(), mExpandedViewManager.get(), + mTaskViewFactory.get(), mPositioner.get(), mStackView.get(), mIconFactory, + mBubble, mSkipInflation); + } + } + + @Override + protected void onPostExecute(BubbleViewInfo viewInfo) { + if (isCancelled() || viewInfo == null) { + return; + } + + mMainExecutor.execute(() -> { + if (!verifyState()) { + return; + } + mBubble.setViewInfoLegacy(viewInfo); + if (mCallback != null) { + mCallback.onBubbleViewsReady(mBubble); + } + }); + } + + private boolean verifyState() { + if (mExpandedViewManager.get().isShowingAsBubbleBar()) { + return mLayerView.get() != null; + } else { + return mStackView.get() != null; + } + } + + /** + * Info necessary to render a bubble. + */ + @VisibleForTesting + public static class BubbleViewInfo { + // TODO(b/273312602): for foldables it might make sense to populate all of the views + + // Always populated + ShortcutInfo shortcutInfo; + String appName; + Bitmap rawBadgeBitmap; + + // Only populated when showing in taskbar + @Nullable BubbleBarExpandedView bubbleBarExpandedView; + + // These are only populated when not showing in taskbar + @Nullable BadgedImageView imageView; + @Nullable BubbleExpandedView expandedView; + int dotColor; + Path dotPath; + @Nullable Bubble.FlyoutMessage flyoutMessage; + Bitmap bubbleBitmap; + Bitmap badgeBitmap; + + @Nullable + public static BubbleViewInfo populateForBubbleBar(Context c, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, + BubbleBarLayerView layerView, + BubbleIconFactory iconFactory, + Bubble b, + boolean skipInflation) { + BubbleViewInfo info = new BubbleViewInfo(); + + if (!skipInflation && !b.isInflated()) { + BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory); + LayoutInflater inflater = LayoutInflater.from(c); + info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate( + R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */); + info.bubbleBarExpandedView.initialize( + expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView); + } + + if (!populateCommonInfo(info, c, b, iconFactory)) { + // if we failed to update common fields return null + return null; + } + + return info; + } + + @VisibleForTesting + @Nullable + public static BubbleViewInfo populate(Context c, + BubbleExpandedViewManager expandedViewManager, + BubbleTaskViewFactory taskViewFactory, + BubblePositioner positioner, + BubbleStackView stackView, + BubbleIconFactory iconFactory, + Bubble b, + boolean skipInflation) { + BubbleViewInfo info = new BubbleViewInfo(); + + // View inflation: only should do this once per bubble + if (!skipInflation && !b.isInflated()) { + LayoutInflater inflater = LayoutInflater.from(c); + info.imageView = (BadgedImageView) inflater.inflate( + R.layout.bubble_view, stackView, false /* attachToRoot */); + info.imageView.initialize(positioner); + + BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory); + info.expandedView = (BubbleExpandedView) inflater.inflate( + R.layout.bubble_expanded_view, stackView, false /* attachToRoot */); + info.expandedView.initialize( + expandedViewManager, stackView, positioner, false /* isOverflow */, + bubbleTaskView); + } + + if (!populateCommonInfo(info, c, b, iconFactory)) { + // if we failed to update common fields return null + return null; + } + + // Flyout + info.flyoutMessage = b.getFlyoutMessage(); + if (info.flyoutMessage != null) { + info.flyoutMessage.senderAvatar = + loadSenderAvatar(c, info.flyoutMessage.senderIcon); + } + return info; + } + } + + /** + * Modifies the given {@code info} object and populates common fields in it. + * + * <p>This method returns {@code true} if the update was successful and {@code false} otherwise. + * Callers should assume that the info object is unusable if the update was unsuccessful. + */ + private static boolean populateCommonInfo( + BubbleViewInfo info, Context c, Bubble b, BubbleIconFactory iconFactory) { + if (b.getShortcutInfo() != null) { + info.shortcutInfo = b.getShortcutInfo(); + } + + // App name & app icon + PackageManager pm = BubbleController.getPackageManagerForUser(c, + b.getUser().getIdentifier()); + ApplicationInfo appInfo; + Drawable badgedIcon; + Drawable appIcon; + try { + appInfo = pm.getApplicationInfo( + b.getPackageName(), + PackageManager.MATCH_UNINSTALLED_PACKAGES + | PackageManager.MATCH_DISABLED_COMPONENTS + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE + | PackageManager.MATCH_DIRECT_BOOT_AWARE); + if (appInfo != null) { + info.appName = String.valueOf(pm.getApplicationLabel(appInfo)); + } + appIcon = pm.getApplicationIcon(b.getPackageName()); + badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser()); + } catch (PackageManager.NameNotFoundException exception) { + // If we can't find package... don't think we should show the bubble. + Log.w(TAG, "Unable to find package: " + b.getPackageName()); + return false; + } + + Drawable bubbleDrawable = null; + try { + // Badged bubble image + bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo, + b.getIcon()); + } catch (Exception e) { + // If we can't create the icon we'll default to the app icon + Log.w(TAG, "Exception creating icon for the bubble: " + b.getKey()); + } + + if (bubbleDrawable == null) { + // Default to app icon + bubbleDrawable = appIcon; + } + + BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon, + b.isImportantConversation()); + info.badgeBitmap = badgeBitmapInfo.icon; + // Raw badge bitmap never includes the important conversation ring + info.rawBadgeBitmap = b.isImportantConversation() + ? iconFactory.getBadgeBitmap(badgedIcon, false).icon + : badgeBitmapInfo.icon; + + float[] bubbleBitmapScale = new float[1]; + info.bubbleBitmap = iconFactory.getBubbleBitmap(bubbleDrawable, bubbleBitmapScale); + + // Dot color & placement + Path iconPath = PathParser.createPathFromPathData( + c.getResources().getString(com.android.internal.R.string.config_icon_mask)); + Matrix matrix = new Matrix(); + float scale = bubbleBitmapScale[0]; + float radius = DEFAULT_PATH_SIZE / 2f; + matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */, + radius /* pivot y */); + iconPath.transform(matrix); + info.dotPath = iconPath; + info.dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color, + Color.WHITE, WHITE_SCRIM_ALPHA); + return true; + } + + @Nullable + static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) { + Objects.requireNonNull(context); + if (icon == null) return null; + try { + if (icon.getType() == Icon.TYPE_URI + || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) { + context.grantUriPermission(context.getPackageName(), + icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + return icon.loadDrawable(context); + } catch (Exception e) { + Log.w(TAG, "loadSenderAvatar failed: " + e.getMessage()); + return null; + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt index da71b1c741bb..39a2a7b868a0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt @@ -27,7 +27,7 @@ import android.widget.Button import android.widget.LinearLayout import com.android.internal.R.color.system_neutral1_900 import com.android.wm.shell.R -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators /** * User education view to highlight the manage button that allows a user to configure the settings diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt index c4108c4129e9..16606198b240 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt @@ -26,7 +26,7 @@ import android.widget.LinearLayout import android.widget.TextView import com.android.internal.util.ContrastColorUtil import com.android.wm.shell.R -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators /** * User education view to highlight the collapsed stack of bubbles. Shown only the first time a user diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java index f925eaef2c77..8f0dfb9e2215 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java @@ -33,13 +33,13 @@ import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringForce; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.bubbles.BadgedImageView; import com.android.wm.shell.bubbles.BubbleOverflow; import com.android.wm.shell.bubbles.BubblePositioner; import com.android.wm.shell.bubbles.BubbleStackView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import com.google.android.collect.Sets; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedViewAnimationControllerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedViewAnimationControllerImpl.java index fbef6b5e4a99..7cb537a24ce2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedViewAnimationControllerImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedViewAnimationControllerImpl.java @@ -40,9 +40,9 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.animation.FlingAnimationUtils; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.bubbles.BubbleExpandedView; import com.android.wm.shell.bubbles.BubblePositioner; +import com.android.wm.shell.shared.animation.Interpolators; import java.util.ArrayList; import java.util.List; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java index 47d4d07500d5..91585dc425eb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java @@ -42,8 +42,8 @@ import com.android.wm.shell.bubbles.BadgedImageView; import com.android.wm.shell.bubbles.BubblePositioner; import com.android.wm.shell.bubbles.BubbleStackView; import com.android.wm.shell.common.FloatingContentCoordinator; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import com.google.android.collect.Sets; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java index 8e58db198b13..565fde0a853c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java @@ -24,9 +24,9 @@ import static android.view.View.VISIBLE; import static android.view.View.X; import static android.view.View.Y; -import static com.android.wm.shell.animation.Interpolators.EMPHASIZED; -import static com.android.wm.shell.animation.Interpolators.EMPHASIZED_DECELERATE; import static com.android.wm.shell.bubbles.bar.BubbleBarExpandedView.CORNER_RADIUS; +import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED; +import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED_DECELERATE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -42,13 +42,13 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.bubbles.BubbleOverflow; import com.android.wm.shell.bubbles.BubblePositioner; import com.android.wm.shell.bubbles.BubbleViewProvider; import com.android.wm.shell.bubbles.animation.AnimatableScaleMatrix; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject.MagneticTarget; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject.MagneticTarget; /** * Helper class to animate a {@link BubbleBarExpandedView} on a bubble. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt index d45ed0d28f3b..eeb5c94c8f81 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt @@ -22,7 +22,7 @@ import android.view.View import com.android.wm.shell.bubbles.BubblePositioner import com.android.wm.shell.common.bubbles.DismissView import com.android.wm.shell.common.bubbles.RelativeTouchListener -import com.android.wm.shell.common.magnetictarget.MagnetizedObject +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject /** Controller for handling drag interactions with [BubbleBarExpandedView] */ @SuppressLint("ClickableViewAccessibility") diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java index 9fa85cf0c57c..ac424532e87b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java @@ -16,8 +16,8 @@ package com.android.wm.shell.bubbles.bar; -import static com.android.wm.shell.animation.Interpolators.ALPHA_IN; -import static com.android.wm.shell.animation.Interpolators.ALPHA_OUT; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_IN; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_OUT; import static com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_GESTURE; import android.annotation.Nullable; 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 3fa51a909aaa..5b01a0d87b5e 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 @@ -52,6 +52,7 @@ import android.view.inputmethod.InputMethodManagerGlobal; import androidx.annotation.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import java.util.ArrayList; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java index f7923924789e..bcd40a9a9765 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java @@ -29,6 +29,7 @@ import android.window.WindowContainerTransactionCallback; import android.window.WindowOrganizer; import com.android.internal.protolog.ProtoLog; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.transition.LegacyTransitions; import java.util.ArrayList; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java index 999da2443248..bdbd4cfef7f5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java @@ -32,7 +32,7 @@ import android.util.Property; import android.view.View; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.shared.animation.Interpolators; /** * View for the handle in the docked stack divider. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java index 2e1789a51dff..8156a9c8d04a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerSnapAlgorithm.java @@ -19,14 +19,14 @@ package com.android.wm.shell.common.split; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_30_70; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_70_30; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_MINIMIZE; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_NONE; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; -import static com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_30_70; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_70_30; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_MINIMIZE; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_NONE; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SnapPosition; import android.content.res.Resources; import android.graphics.Rect; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java index 1bc179551825..442036ff5781 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java @@ -56,8 +56,8 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; /** * Divider for multi window splits. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java index e2988bc6f2aa..7175e361f91a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java @@ -25,8 +25,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.wm.shell.common.split.SplitLayout.BEHIND_APP_VEIL_LAYER; import static com.android.wm.shell.common.split.SplitLayout.FRONT_APP_VEIL_LAYER; -import static com.android.wm.shell.common.split.SplitScreenConstants.FADE_DURATION; -import static com.android.wm.shell.common.split.SplitScreenConstants.VEIL_DELAY_DURATION; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FADE_DURATION; +import static com.android.wm.shell.shared.split.SplitScreenConstants.VEIL_DELAY_DURATION; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; 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 0e050694c733..2a934cba1b50 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 @@ -26,13 +26,15 @@ import static android.view.WindowManager.DOCKED_TOP; import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER; import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE; -import static com.android.wm.shell.animation.Interpolators.DIM_INTERPOLATOR; -import static com.android.wm.shell.animation.Interpolators.SLOWDOWN_INTERPOLATOR; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.animation.Interpolators.DIM_INTERPOLATOR; +import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED; +import static com.android.wm.shell.shared.animation.Interpolators.LINEAR; +import static com.android.wm.shell.shared.animation.Interpolators.SLOWDOWN_INTERPOLATOR; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; import android.animation.Animator; @@ -65,15 +67,15 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.animation.Interpolators; 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.pip.PipUtils; -import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; -import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; +import com.android.wm.shell.shared.animation.Interpolators; +import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.StageTaskListener; @@ -813,7 +815,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange float growPortion = 1 - shrinkPortion; ValueAnimator animator = ValueAnimator.ofFloat(0, 1); - animator.setInterpolator(Interpolators.EMPHASIZED); + // Set the base animation to proceed linearly. Each component of the animation (movement, + // shrinking, growing) overrides it with a different interpolator later. + animator.setInterpolator(LINEAR); animator.addUpdateListener(animation -> { if (leash == null) return; if (roundCorners) { @@ -822,10 +826,11 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } final float progress = (float) animation.getAnimatedValue(); - float instantaneousX = tempStart.left + progress * diffX; - float instantaneousY = tempStart.top + progress * diffY; - int width = (int) (tempStart.width() + progress * diffWidth); - int height = (int) (tempStart.height() + progress * diffHeight); + final float moveProgress = EMPHASIZED.getInterpolation(progress); + float instantaneousX = tempStart.left + moveProgress * diffX; + float instantaneousY = tempStart.top + moveProgress * diffY; + int width = (int) (tempStart.width() + moveProgress * diffWidth); + int height = (int) (tempStart.height() + moveProgress * diffHeight); if (isGoingBehind) { float shrinkDiffX; // the position adjustments needed for this frame @@ -897,8 +902,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange taskInfo, mTempRect, t, isGoingBehind, leash, 0, 0); } } else { - final int diffOffsetX = (int) (progress * offsetX); - final int diffOffsetY = (int) (progress * offsetY); + final int diffOffsetX = (int) (moveProgress * offsetX); + final int diffOffsetY = (int) (moveProgress * offsetY); t.setPosition(leash, instantaneousX + diffOffsetX, instantaneousY + diffOffsetY); mTempRect.set(0, 0, width, height); mTempRect.offsetTo(-diffOffsetX, -diffOffsetY); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java index f9259e79472e..bdbcb4635ae8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java @@ -16,34 +16,25 @@ package com.android.wm.shell.common.split; -import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED; - -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import android.app.ActivityManager; import android.app.PendingIntent; -import android.content.ComponentName; import android.content.Intent; -import android.content.pm.LauncherApps; -import android.content.pm.ShortcutInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; -import android.os.UserHandle; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.util.ArrayUtils; import com.android.wm.shell.Flags; import com.android.wm.shell.ShellTaskOrganizer; - -import java.util.Arrays; -import java.util.List; +import com.android.wm.shell.shared.split.SplitScreenConstants; /** Helper utility class for split screen components to use. */ public class SplitScreenUtils { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt index 9ee50ac3c221..831b331a11e9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt @@ -16,28 +16,222 @@ package com.android.wm.shell.compatui.api -import android.util.Log +import android.content.Context +import android.content.res.Configuration +import android.graphics.PixelFormat +import android.graphics.Point +import android.os.Binder +import android.view.IWindow +import android.view.SurfaceControl +import android.view.SurfaceControlViewHost +import android.view.SurfaceSession +import android.view.View +import android.view.WindowManager +import android.view.WindowlessWindowManager +import com.android.wm.shell.common.DisplayLayout +import com.android.wm.shell.common.SyncTransactionQueue /** * The component created after a {@link CompatUISpec} definition */ class CompatUIComponent( private val spec: CompatUISpec, - private val id: String + private val id: String, + private var context: Context, + private val state: CompatUIState, + private var compatUIInfo: CompatUIInfo, + private val syncQueue: SyncTransactionQueue, + private var displayLayout: DisplayLayout? +) : WindowlessWindowManager( + compatUIInfo.taskInfo.configuration, + /* rootSurface */ + null, + /* hostInputToken */ + null ) { + private val tag + get() = "CompatUI {id = $id}" + + private var leash: SurfaceControl? = null + + private var layout: View? = null + + /** + * Utility class for adding and releasing a View hierarchy for this [ ] to `mLeash`. + */ + protected var viewHost: SurfaceControlViewHost? = null + + override fun setConfiguration(configuration: Configuration?) { + super.setConfiguration(configuration) + configuration?.let { + context = context.createConfigurationContext(it) + } + } + /** * Invoked every time a new CompatUIInfo comes from core * @param newInfo The new CompatUIInfo object - * @param sharedState The state shared between all the component */ - fun update(newInfo: CompatUIInfo, state: CompatUIState) { - // TODO(b/322817374): To be removed when the implementation is provided. - Log.d("CompatUIComponent", "update() newInfo: $newInfo state:$state") + fun update(newInfo: CompatUIInfo) { + updateComponentState(newInfo, state.stateForComponent(id)) + updateUI(state) } fun release() { - // TODO(b/322817374): To be removed when the implementation is provided. - Log.d("CompatUIComponent", "release()") + spec.log("$tag releasing.....") + // Implementation empty + // Hiding before releasing to avoid flickering when transitioning to the Home screen. + layout?.visibility = View.GONE + layout = null + spec.layout.viewReleaser() + spec.log("$tag layout releaser invoked!") + viewHost?.release() + viewHost = null + leash?.run { + val localLeash: SurfaceControl = this + syncQueue.runInSync { t: SurfaceControl.Transaction -> + t.remove( + localLeash + ) + } + leash = null + spec.log("$tag leash removed") + } + spec.log("$tag released") + } + + override fun getParentSurface( + window: IWindow, + attrs: WindowManager.LayoutParams + ): SurfaceControl? { + val className = javaClass.simpleName + val builder = SurfaceControl.Builder(SurfaceSession()) + .setContainerLayer() + .setName(className + "Leash") + .setHidden(false) + .setCallsite("$className#attachToParentSurface") + attachToParentSurface(builder) + leash = builder.build() + initSurface(leash) + return leash + } + + fun attachToParentSurface(builder: SurfaceControl.Builder) { + compatUIInfo.listener?.attachChildSurfaceToTask(compatUIInfo.taskInfo.taskId, builder) + } + + fun initLayout(newCompatUIInfo: CompatUIInfo) { + compatUIInfo = newCompatUIInfo + spec.log("$tag updating...") + check(viewHost == null) { "A UI has already been created with this window manager." } + val componentState: CompatUIComponentState? = state.stateForComponent(id) + spec.log("$tag state: $componentState") + // We inflate the layout + layout = spec.layout.viewBuilder(context, compatUIInfo, componentState) + spec.log("$tag layout: $layout") + viewHost = createSurfaceViewHost().apply { + spec.log("$tag adding view $layout to host $this") + setView(layout!!, getWindowLayoutParams()) + } + updateSurfacePosition() + } + + /** Creates a [SurfaceControlViewHost] for this window manager. */ + fun createSurfaceViewHost(): SurfaceControlViewHost = + SurfaceControlViewHost(context, context.display, this, javaClass.simpleName) + + fun relayout() { + spec.log("$tag relayout...") + viewHost?.run { + relayout(getWindowLayoutParams()) + updateSurfacePosition() + } + } + + protected fun updateSurfacePosition() { + spec.log("$tag updateSurfacePosition on layout $layout") + layout?.let { + updateSurfacePosition( + spec.layout.positionFactory( + it, + compatUIInfo, + state.sharedState, + state.stateForComponent(id) + ) + ) + } + } + + protected fun getWindowLayoutParams(width: Int, height: Int): WindowManager.LayoutParams { + // Cannot be wrap_content as this determines the actual window size + val winParams = + WindowManager.LayoutParams( + width, + height, + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + spec.layout.layoutParamFlags, + PixelFormat.TRANSLUCENT + ) + winParams.token = Binder() + winParams.title = javaClass.simpleName + compatUIInfo.taskInfo.taskId + winParams.privateFlags = + winParams.privateFlags or (WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION + or WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) + spec.log("$tag getWindowLayoutParams $winParams") + return winParams + } + + /** Gets the layout params. */ + protected fun getWindowLayoutParams(): WindowManager.LayoutParams = + layout?.run { + measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) + spec.log( + "$tag getWindowLayoutParams size: ${measuredWidth}x$measuredHeight" + ) + return getWindowLayoutParams(measuredWidth, measuredHeight) + } ?: WindowManager.LayoutParams() + + protected fun updateSurfacePosition(position: Point) { + spec.log("$tag updateSurfacePosition on leash $leash") + leash?.run { + syncQueue.runInSync { t: SurfaceControl.Transaction -> + if (!isValid) { + spec.log("$tag The leash has been released.") + return@runInSync + } + spec.log("$tag settings position $position") + t.setPosition(this, position.x.toFloat(), position.y.toFloat()) + } + } + } + + private fun updateComponentState( + newInfo: CompatUIInfo, + componentState: CompatUIComponentState? + ) { + spec.log("$tag component state updating.... $componentState") + compatUIInfo = newInfo + } + + private fun updateUI(state: CompatUIState) { + spec.log("$tag updating ui") + setConfiguration(compatUIInfo.taskInfo.configuration) + val componentState: CompatUIComponentState? = state.stateForComponent(id) + layout?.run { + spec.log("$tag viewBinder execution...") + spec.layout.viewBinder(this, compatUIInfo, state.sharedState, componentState) + relayout() + } + } + + private fun initSurface(leash: SurfaceControl?) { + syncQueue.runInSync { t: SurfaceControl.Transaction -> + if (leash == null || !leash.isValid) { + spec.log("$tag The leash has been released.") + return@runInSync + } + t.setLayer(leash, spec.layout.zOrder) + } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentFactory.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentFactory.kt new file mode 100644 index 000000000000..55821ffdb6bd --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentFactory.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.api + +/** + * Abstracts the component responsible for the creation of a component + */ +interface CompatUIComponentFactory { + + fun create( + spec: CompatUISpec, + compId: String, + state: CompatUIState, + compatUIInfo: CompatUIInfo, + ): CompatUIComponent +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt index dcaea000d0a1..ec21924fbe16 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponentState.kt @@ -18,7 +18,6 @@ package com.android.wm.shell.compatui.api /** * Abstraction of all the component specific state. Each - * component can create its own state implementing this - * tagging interface. + * component can create its own state implementing this interface. */ -interface CompatUIComponentState
\ No newline at end of file +interface CompatUIComponentState diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt index 022906cf568c..de400f49d64b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUISpec.kt @@ -16,6 +16,11 @@ package com.android.wm.shell.compatui.api +import android.content.Context +import android.graphics.Point +import android.view.View +import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE +import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL import com.android.internal.protolog.ProtoLog import com.android.wm.shell.protolog.ShellProtoLogGroup @@ -39,6 +44,28 @@ class CompatUILifecyclePredicates( ) /** + * Layout configuration + */ +data class CompatUILayout( + val zOrder: Int = 0, + val layoutParamFlags: Int = FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL, + val viewBuilder: (Context, CompatUIInfo, CompatUIComponentState?) -> View, + val viewBinder: ( + View, + CompatUIInfo, + CompatUISharedState, + CompatUIComponentState? + ) -> Unit = { _, _, _, _ -> }, + val positionFactory: ( + View, + CompatUIInfo, + CompatUISharedState, + CompatUIComponentState? + ) -> Point, + val viewReleaser: () -> Unit = {} +) + +/** * Describes each compat ui component to the framework. */ class CompatUISpec( @@ -47,5 +74,7 @@ class CompatUISpec( // unique component identifier in the system. val name: String, // The lifecycle definition - val lifecycle: CompatUILifecyclePredicates + val lifecycle: CompatUILifecyclePredicates, + // The layout definition + val layout: CompatUILayout ) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/components/RestartButtonSpec.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/components/RestartButtonSpec.kt new file mode 100644 index 000000000000..e18cc0e5d416 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/components/RestartButtonSpec.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.components + +import android.annotation.SuppressLint +import android.graphics.Point +import android.view.LayoutInflater +import android.view.View +import android.window.TaskConstants +import com.android.wm.shell.R +import com.android.wm.shell.compatui.api.CompatUILayout +import com.android.wm.shell.compatui.api.CompatUILifecyclePredicates +import com.android.wm.shell.compatui.api.CompatUISpec + +/** + * CompatUISpec for the Restart Button + */ +@SuppressLint("InflateParams") +val RestartButtonSpec = CompatUISpec( + name = "restartButton", + lifecycle = CompatUILifecyclePredicates( + creationPredicate = { info, _ -> + info.taskInfo.appCompatTaskInfo.isTopActivityInSizeCompat + }, + removalPredicate = { info, _, _ -> + !info.taskInfo.appCompatTaskInfo.isTopActivityInSizeCompat + } + ), + layout = CompatUILayout( + zOrder = TaskConstants.TASK_CHILD_LAYER_COMPAT_UI + 10, + viewBuilder = { ctx, _, _ -> + LayoutInflater.from(ctx).inflate( + R.layout.compat_ui_restart_button_layout, + null + ) + }, + viewBinder = { view, _, _, _ -> + view.visibility = View.VISIBLE + view.findViewById<View>(R.id.size_compat_restart_button)?.visibility = View.VISIBLE + }, + // TODO(b/360288344): Calculate right position from stable bounds + positionFactory = { _, _, _, _ -> Point(500, 500) } + ) +) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIComponentFactory.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIComponentFactory.kt new file mode 100644 index 000000000000..4eea6a31dd27 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIComponentFactory.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.impl + +import android.content.Context +import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.compatui.api.CompatUIComponent +import com.android.wm.shell.compatui.api.CompatUIComponentFactory +import com.android.wm.shell.compatui.api.CompatUIInfo +import com.android.wm.shell.compatui.api.CompatUISpec +import com.android.wm.shell.compatui.api.CompatUIState + +/** + * Default {@link CompatUIComponentFactory } implementation + */ +class DefaultCompatUIComponentFactory( + private val context: Context, + private val syncQueue: SyncTransactionQueue, + private val displayController: DisplayController +) : CompatUIComponentFactory { + override fun create( + spec: CompatUISpec, + compId: String, + state: CompatUIState, + compatUIInfo: CompatUIInfo + ): CompatUIComponent = + CompatUIComponent( + spec, + compId, + context, + state, + compatUIInfo, + syncQueue, + displayController.getDisplayLayout(compatUIInfo.taskInfo.displayId) + ) +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt index a7d1b4218a24..02db85a4f99d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandler.kt @@ -16,7 +16,8 @@ package com.android.wm.shell.compatui.impl -import com.android.wm.shell.compatui.api.CompatUIComponent +import com.android.wm.shell.common.ShellExecutor +import com.android.wm.shell.compatui.api.CompatUIComponentFactory import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator import com.android.wm.shell.compatui.api.CompatUIEvent import com.android.wm.shell.compatui.api.CompatUIHandler @@ -24,7 +25,6 @@ import com.android.wm.shell.compatui.api.CompatUIInfo import com.android.wm.shell.compatui.api.CompatUIRepository import com.android.wm.shell.compatui.api.CompatUIState import java.util.function.Consumer -import java.util.function.IntSupplier /** * Default implementation of {@link CompatUIHandler} to handle CompatUI components @@ -32,7 +32,9 @@ import java.util.function.IntSupplier class DefaultCompatUIHandler( private val compatUIRepository: CompatUIRepository, private val compatUIState: CompatUIState, - private val componentIdGenerator: CompatUIComponentIdGenerator + private val componentIdGenerator: CompatUIComponentIdGenerator, + private val componentFactory: CompatUIComponentFactory, + private val executor: ShellExecutor ) : CompatUIHandler { private var compatUIEventSender: Consumer<CompatUIEvent>? = null @@ -41,23 +43,36 @@ class DefaultCompatUIHandler( compatUIRepository.iterateOn { spec -> // We get the identifier for the component depending on the task and spec val componentId = componentIdGenerator.generateId(compatUIInfo, spec) - // We check in the state if the component already exists - var comp = compatUIState.getUIComponent(componentId) - if (comp == null) { + spec.log("Evaluating component $componentId") + // We check in the state if the component does not yet exist + var component = compatUIState.getUIComponent(componentId) + if (component == null) { + spec.log("Component $componentId not present") // We evaluate the predicate if (spec.lifecycle.creationPredicate(compatUIInfo, compatUIState.sharedState)) { + spec.log("Component $componentId should be created") // We create the component and store in the // global state - comp = CompatUIComponent(spec, componentId) + component = + componentFactory.create(spec, componentId, compatUIState, compatUIInfo) + spec.log("Component $componentId created $component") // We initialize the state for the component val compState = spec.lifecycle.stateBuilder( compatUIInfo, compatUIState.sharedState ) - compatUIState.registerUIComponent(componentId, comp, compState) + spec.log("Component $componentId initial state $compState") + compatUIState.registerUIComponent(componentId, component, compState) + spec.log("Component $componentId registered") + // We initialize the layout for the component + component.initLayout(compatUIInfo) + spec.log("Component $componentId layout created") // Now we can invoke the update passing the shared state and // the state specific to the component - comp.update(compatUIInfo, compatUIState) + executor.execute { + component.update(compatUIInfo) + spec.log("Component $componentId updated with $compatUIInfo") + } } } else { // The component is present. We check if we need to remove it @@ -66,13 +81,18 @@ class DefaultCompatUIHandler( compatUIState.sharedState, compatUIState.stateForComponent(componentId) )) { + spec.log("Component $componentId should be removed") // We clean the component - comp.release() - // We remove the component + component.release() + spec.log("Component $componentId released") compatUIState.unregisterUIComponent(componentId) + spec.log("Component $componentId removed from registry") } else { - // The component exists so we need to invoke the update methods - comp.update(compatUIInfo, compatUIState) + executor.execute { + // The component exists so we need to invoke the update methods + component.update(compatUIInfo) + spec.log("Component $componentId updated with $compatUIInfo") + } } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java index 011093718671..33e4fd8c1a46 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java @@ -30,9 +30,9 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.dagger.pip.TvPipModule; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.tv.TvSplitScreenController; 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 04cd225ea4a3..98536bf98f0b 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 @@ -62,7 +62,6 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.pip.PhonePipKeepClearAlgorithm; import com.android.wm.shell.common.pip.PhoneSizeSpecSource; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; @@ -77,10 +76,13 @@ import com.android.wm.shell.compatui.CompatUIConfiguration; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.compatui.CompatUIShellCommandHandler; import com.android.wm.shell.compatui.CompatUIStatusManager; +import com.android.wm.shell.compatui.api.CompatUIComponentFactory; import com.android.wm.shell.compatui.api.CompatUIComponentIdGenerator; import com.android.wm.shell.compatui.api.CompatUIHandler; import com.android.wm.shell.compatui.api.CompatUIRepository; import com.android.wm.shell.compatui.api.CompatUIState; +import com.android.wm.shell.compatui.components.RestartButtonSpecKt; +import com.android.wm.shell.compatui.impl.DefaultCompatUIComponentFactory; import com.android.wm.shell.compatui.impl.DefaultCompatUIHandler; import com.android.wm.shell.compatui.impl.DefaultCompatUIRepository; import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator; @@ -102,6 +104,7 @@ import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.recents.RecentsTransitionHandler; import com.android.wm.shell.recents.TaskStackTransitionObserver; import com.android.wm.shell.shared.ShellTransitions; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.annotations.ShellAnimationThread; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; @@ -260,13 +263,15 @@ public abstract class WMShellBaseModule { CompatUIRepository compatUIRepository, @NonNull CompatUIState compatUIState, @NonNull CompatUIComponentIdGenerator componentIdGenerator, + @NonNull CompatUIComponentFactory compatUIComponentFactory, CompatUIStatusManager compatUIStatusManager) { if (!context.getResources().getBoolean(R.bool.config_enableCompatUIController)) { return Optional.empty(); } if (Flags.appCompatUiFramework()) { - return Optional.of(new DefaultCompatUIHandler(compatUIRepository, compatUIState, - componentIdGenerator)); + return Optional.of( + new DefaultCompatUIHandler(compatUIRepository, compatUIState, + componentIdGenerator, compatUIComponentFactory, mainExecutor)); } return Optional.of( new CompatUIController( @@ -308,6 +313,15 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides + static CompatUIComponentFactory provideCompatUIComponentFactory( + @NonNull Context context, + @NonNull SyncTransactionQueue syncQueue, + @NonNull DisplayController displayController) { + return new DefaultCompatUIComponentFactory(context, syncQueue, displayController); + } + + @WMSingleton + @Provides static CompatUIComponentIdGenerator provideCompatUIComponentIdGenerator() { return new DefaultComponentIdGenerator(); } @@ -315,7 +329,10 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides static CompatUIRepository provideCompatUIRepository() { - return new DefaultCompatUIRepository(); + // TODO(b/360288344) Integrate Dagger Multibinding + final CompatUIRepository repository = new DefaultCompatUIRepository(); + repository.addSpec(RestartButtonSpecKt.getRestartButtonSpec()); + return repository; } @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 955361ffac1b..ce054a833107 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 @@ -56,10 +56,10 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.dagger.back.ShellBackAnimationModule; import com.android.wm.shell.dagger.pip.PipModule; import com.android.wm.shell.desktopmode.DefaultDragToDesktopTransitionHandler; +import com.android.wm.shell.desktopmode.DesktopModeDragAndDropTransitionHandler; import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopModeLoggerTransitionObserver; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; @@ -84,6 +84,7 @@ import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.recents.RecentsTransitionHandler; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.annotations.ShellAnimationThread; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; @@ -164,8 +165,10 @@ public abstract class WMShellModule { BubbleLogger logger, BubblePositioner positioner, BubbleEducationController educationController, - @ShellMainThread ShellExecutor mainExecutor) { - return new BubbleData(context, logger, positioner, educationController, mainExecutor); + @ShellMainThread ShellExecutor mainExecutor, + @ShellBackgroundThread ShellExecutor bgExecutor) { + return new BubbleData(context, logger, positioner, educationController, mainExecutor, + bgExecutor); } // Note: Handler needed for LauncherApps.register @@ -198,7 +201,7 @@ public abstract class WMShellModule { IWindowManager wmService) { return new BubbleController(context, shellInit, shellCommandHandler, shellController, data, null /* synchronizer */, floatingContentCoordinator, - new BubbleDataRepository(launcherApps, mainExecutor, + new BubbleDataRepository(launcherApps, mainExecutor, bgExecutor, new BubblePersistentRepository(context)), statusBarService, windowManager, windowManagerShellWrapper, userManager, launcherApps, logger, taskStackListener, organizer, positioner, displayController, @@ -301,6 +304,7 @@ public abstract class WMShellModule { ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorViewModel) { // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic // override for this controller from the base module @@ -308,7 +312,7 @@ public abstract class WMShellModule { ? shellInit : null; return new FreeformTaskListener(context, init, shellTaskOrganizer, - desktopModeTaskRepository, windowDecorViewModel); + desktopModeTaskRepository, launchAdjacentController, windowDecorViewModel); } @WMSingleton @@ -556,6 +560,7 @@ public abstract class WMShellModule { ReturnToDragStartAnimator returnToDragStartAnimator, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, + DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, DragToDesktopTransitionHandler dragToDesktopTransitionHandler, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, @@ -571,7 +576,8 @@ public abstract class WMShellModule { displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, dragAndDropController, transitions, keyguardManager, returnToDragStartAnimator, enterDesktopTransitionHandler, - exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler, + exitDesktopTransitionHandler, desktopModeDragAndDropTransitionHandler, + toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, desktopModeTaskRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter, @@ -606,8 +612,8 @@ public abstract class WMShellModule { @WMSingleton @Provides static ReturnToDragStartAnimator provideReturnToDragStartAnimator( - InteractionJankMonitor interactionJankMonitor) { - return new ReturnToDragStartAnimator(interactionJankMonitor); + Context context, InteractionJankMonitor interactionJankMonitor) { + return new ReturnToDragStartAnimator(context, interactionJankMonitor); } @@ -653,6 +659,14 @@ public abstract class WMShellModule { @WMSingleton @Provides + static DesktopModeDragAndDropTransitionHandler provideDesktopModeDragAndDropTransitionHandler( + Transitions transitions + ) { + return new DesktopModeDragAndDropTransitionHandler(transitions); + } + + @WMSingleton + @Provides @DynamicOverride static DesktopModeTaskRepository provideDesktopModeTaskRepository() { return new DesktopModeTaskRepository(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java index 06c1e68753e1..51ce2c6707ac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java @@ -45,6 +45,7 @@ import com.android.wm.shell.pip2.phone.PipScheduler; import com.android.wm.shell.pip2.phone.PipTouchHandler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.pip2.phone.PipTransitionState; +import com.android.wm.shell.pip2.phone.PipUiStateChangeController; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; @@ -73,10 +74,11 @@ public abstract class Pip2Module { Optional<PipController> pipController, PipTouchHandler pipTouchHandler, @NonNull PipScheduler pipScheduler, - @NonNull PipTransitionState pipStackListenerController) { + @NonNull PipTransitionState pipStackListenerController, + @NonNull PipUiStateChangeController pipUiStateChangeController) { return new PipTransition(context, shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm, pipScheduler, - pipStackListenerController); + pipStackListenerController, pipUiStateChangeController); } @WMSingleton @@ -181,4 +183,11 @@ public abstract class Pip2Module { static PipTransitionState providePipTransitionState(@ShellMainThread Handler handler) { return new PipTransitionState(handler); } + + @WMSingleton + @Provides + static PipUiStateChangeController providePipUiStateChangeController( + PipTransitionState pipTransitionState) { + return new PipUiStateChangeController(pipTransitionState); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt new file mode 100644 index 000000000000..a7a4a1036b5d --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.wm.shell.desktopmode + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.ValueAnimator +import android.os.IBinder +import android.view.SurfaceControl +import android.view.WindowManager.TRANSIT_OPEN +import android.window.TransitionInfo +import android.window.TransitionRequestInfo +import android.window.WindowContainerTransaction +import com.android.wm.shell.transition.Transitions +import com.android.wm.shell.transition.Transitions.TransitionFinishCallback + +/** + * Transition handler for drag-and-drop (i.e., tab tear) transitions that occur in desktop mode. + */ +class DesktopModeDragAndDropTransitionHandler(private val transitions: Transitions) : + Transitions.TransitionHandler { + private val pendingTransitionTokens: MutableList<IBinder> = mutableListOf() + + /** + * Begin a transition when a [android.app.PendingIntent] is dropped without a window to + * accept it. + */ + fun handleDropEvent(wct: WindowContainerTransaction): IBinder { + val token = transitions.startTransition(TRANSIT_OPEN, wct, this) + pendingTransitionTokens.add(token) + return token + } + + override fun startAnimation( + transition: IBinder, + info: TransitionInfo, + startTransaction: SurfaceControl.Transaction, + finishTransaction: SurfaceControl.Transaction, + finishCallback: TransitionFinishCallback + ): Boolean { + if (!pendingTransitionTokens.contains(transition)) return false + val change = findRelevantChange(info) + val leash = change.leash + val endBounds = change.endAbsBounds + startTransaction.hide(leash) + .setWindowCrop(leash, endBounds.width(), endBounds.height()) + .apply() + val animator = ValueAnimator() + animator.setFloatValues(0f, 1f) + animator.setDuration(FADE_IN_ANIMATION_DURATION) + val t = SurfaceControl.Transaction() + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + t.show(leash) + t.apply() + } + + override fun onAnimationEnd(animation: Animator) { + finishCallback.onTransitionFinished(null) + } + }) + animator.addUpdateListener { animation: ValueAnimator -> + t.setAlpha(leash, animation.animatedFraction) + t.apply() + } + animator.start() + pendingTransitionTokens.remove(transition) + return true + } + + private fun findRelevantChange(info: TransitionInfo): TransitionInfo.Change { + val matchingChanges = + info.changes.filter { c -> + isValidTaskChange(c) && c.mode == TRANSIT_OPEN + } + if (matchingChanges.size != 1) { + throw IllegalStateException( + "Expected 1 relevant change but found: ${matchingChanges.size}" + ) + } + return matchingChanges.first() + } + + private fun isValidTaskChange(change: TransitionInfo.Change): Boolean { + return change.taskInfo != null && change.taskInfo?.taskId != -1 + } + + override fun handleRequest( + transition: IBinder, + request: TransitionRequestInfo + ): WindowContainerTransaction? { + return null + } + + companion object { + const val FADE_IN_ANIMATION_DURATION = 300L + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt index 05c9d02a0de7..b6f2a25ff1c0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.desktopmode +import com.android.internal.annotations.VisibleForTesting import com.android.internal.protolog.ProtoLog import com.android.internal.util.FrameworkStatsLog import com.android.wm.shell.protolog.ShellProtoLogGroup @@ -128,7 +129,10 @@ class DesktopModeEventLogger { /* task_y */ taskUpdate.taskY, /* session_id */ - sessionId + sessionId, + taskUpdate.minimizeReason?.reason ?: UNSET_MINIMIZE_REASON, + taskUpdate.unminimizeReason?.reason ?: UNSET_UNMINIMIZE_REASON, + ) } @@ -142,6 +146,8 @@ class DesktopModeEventLogger { * @property taskWidth width of the task in px * @property taskX x-coordinate of the top-left corner * @property taskY y-coordinate of the top-left corner + * @property minimizeReason the reason the task was minimized + * @property unminimizeEvent the reason the task was unminimized * */ data class TaskUpdate( @@ -151,8 +157,52 @@ class DesktopModeEventLogger { val taskWidth: Int, val taskX: Int, val taskY: Int, + val minimizeReason: MinimizeReason? = null, + val unminimizeReason: UnminimizeReason? = null, ) + // Default value used when the task was not minimized. + @VisibleForTesting + const val UNSET_MINIMIZE_REASON = + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__UNSET_MINIMIZE + + /** The reason a task was minimized. */ + enum class MinimizeReason (val reason: Int) { + TASK_LIMIT( + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_TASK_LIMIT + ), + MINIMIZE_BUTTON( // TODO(b/356843241): use this enum value + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_BUTTON + ), + } + + // Default value used when the task was not unminimized. + @VisibleForTesting + const val UNSET_UNMINIMIZE_REASON = + FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNSET_UNMINIMIZE + + /** The reason a task was unminimized. */ + enum class UnminimizeReason (val reason: Int) { + UNKNOWN( + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_UNKNOWN + ), + TASKBAR_TAP( + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_TASKBAR_TAP + ), + ALT_TAB( + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_ALT_TAB + ), + TASK_LAUNCH( + FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_TASK_LAUNCH + ), + } + /** * Enum EnterReason mapped to the EnterReason definition in * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt index 6c03dc333515..b68b436f2c1b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt @@ -66,7 +66,7 @@ fun calculateInitialBounds( val initialSize: Size = when (taskInfo.configuration.orientation) { ORIENTATION_LANDSCAPE -> { - if (taskInfo.isResizeable) { + if (taskInfo.canChangeAspectRatio) { if (isFixedOrientationPortrait(topActivityInfo.screenOrientation)) { // For portrait resizeable activities, respect apps fullscreen width but // apply ideal size height. @@ -85,7 +85,7 @@ fun calculateInitialBounds( ORIENTATION_PORTRAIT -> { val customPortraitWidthForLandscapeApp = screenBounds.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2) - if (taskInfo.isResizeable) { + if (taskInfo.canChangeAspectRatio) { if (isFixedOrientationLandscape(topActivityInfo.screenOrientation)) { // For landscape resizeable activities, respect apps fullscreen height and // apply custom app width. @@ -189,6 +189,13 @@ private fun positionInScreen(desiredSize: Size, stableBounds: Rect): Rect = } /** + * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was + * unresizeable. + */ +private val TaskInfo.canChangeAspectRatio: Boolean + get() = isResizeable && !appCompatTaskInfo.hasMinAspectRatioOverride() + +/** * Adjusts bounds to be positioned in the middle of the area provided, not necessarily the * entire screen, as area can be offset by left and top start. */ @@ -204,7 +211,7 @@ fun centerInArea(desiredSize: Size, areaBounds: Rect, leftStart: Int, topStart: return Rect(newLeft, newTop, newRight, newBottom) } -fun TaskInfo.hasPortraitTopActivity(): Boolean { +private fun TaskInfo.hasPortraitTopActivity(): Boolean { val topActivityScreenOrientation = topActivityInfo?.screenOrientation ?: SCREEN_ORIENTATION_UNSPECIFIED val appBounds = configuration.windowConfiguration.appBounds diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java index 09f9139cb1d5..bfc0ee803591 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java @@ -16,7 +16,6 @@ package com.android.wm.shell.desktopmode; -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -29,7 +28,6 @@ import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Resources; import android.graphics.PixelFormat; @@ -70,6 +68,37 @@ public class DesktopModeVisualIndicator { TO_SPLIT_RIGHT_INDICATOR } + /** + * The conditions surrounding the drag event that led to the indicator's creation. + */ + public enum DragStartState { + /** The indicator is resulting from a freeform task drag. */ + FROM_FREEFORM, + /** The indicator is resulting from a split screen task drag */ + FROM_SPLIT, + /** The indicator is resulting from a fullscreen task drag */ + FROM_FULLSCREEN, + /** The indicator is resulting from an Intent generated during a drag-and-drop event */ + DRAGGED_INTENT; + + /** + * Get the {@link DragStartState} of a drag event based on the windowing mode of the task. + * Note that DRAGGED_INTENT will be specified by the caller if needed and not returned + * here. + */ + public static DesktopModeVisualIndicator.DragStartState getDragStartState( + ActivityManager.RunningTaskInfo taskInfo + ) { + if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + return FROM_FULLSCREEN; + } else if (taskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { + return FROM_SPLIT; + } else if (taskInfo.isFreeform()) { + return FROM_FREEFORM; + } else return null; + } + } + private final Context mContext; private final DisplayController mDisplayController; private final RootTaskDisplayAreaOrganizer mRootTdaOrganizer; @@ -82,11 +111,13 @@ public class DesktopModeVisualIndicator { private View mView; private IndicatorType mCurrentType; + private DragStartState mDragStartState; public DesktopModeVisualIndicator(SyncTransactionQueue syncQueue, ActivityManager.RunningTaskInfo taskInfo, DisplayController displayController, Context context, SurfaceControl taskSurface, - RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer) { + RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer, + DragStartState dragStartState) { mSyncQueue = syncQueue; mTaskInfo = taskInfo; mDisplayController = displayController; @@ -94,6 +125,7 @@ public class DesktopModeVisualIndicator { mTaskSurface = taskSurface; mRootTdaOrganizer = taskDisplayAreaOrganizer; mCurrentType = IndicatorType.NO_INDICATOR; + mDragStartState = dragStartState; } /** @@ -101,7 +133,7 @@ public class DesktopModeVisualIndicator { * display, including no visible indicator. */ @NonNull - IndicatorType updateIndicatorType(PointF inputCoordinates, int windowingMode) { + IndicatorType updateIndicatorType(PointF inputCoordinates) { final DisplayLayout layout = mDisplayController.getDisplayLayout(mTaskInfo.displayId); // If we are in freeform, we don't want a visible indicator in the "freeform" drag zone. IndicatorType result = IndicatorType.NO_INDICATOR; @@ -111,14 +143,13 @@ public class DesktopModeVisualIndicator { // account for the possibility of the task going off the top of the screen by captionHeight final int captionHeight = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_freeform_decor_caption_height); - final Region fullscreenRegion = calculateFullscreenRegion(layout, windowingMode, + final Region fullscreenRegion = calculateFullscreenRegion(layout, captionHeight); + final Region splitLeftRegion = calculateSplitLeftRegion(layout, transitionAreaWidth, captionHeight); - final Region splitLeftRegion = calculateSplitLeftRegion(layout, windowingMode, - transitionAreaWidth, captionHeight); - final Region splitRightRegion = calculateSplitRightRegion(layout, windowingMode, - transitionAreaWidth, captionHeight); - final Region toDesktopRegion = calculateToDesktopRegion(layout, windowingMode, - splitLeftRegion, splitRightRegion, fullscreenRegion); + final Region splitRightRegion = calculateSplitRightRegion(layout, transitionAreaWidth, + captionHeight); + final Region toDesktopRegion = calculateToDesktopRegion(layout, splitLeftRegion, + splitRightRegion, fullscreenRegion); if (fullscreenRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_FULLSCREEN_INDICATOR; } @@ -131,20 +162,22 @@ public class DesktopModeVisualIndicator { if (toDesktopRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_DESKTOP_INDICATOR; } - transitionIndicator(result); + if (mDragStartState != DragStartState.DRAGGED_INTENT) { + transitionIndicator(result); + } return result; } @VisibleForTesting - Region calculateFullscreenRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int captionHeight) { + Region calculateFullscreenRegion(DisplayLayout layout, int captionHeight) { final Region region = new Region(); - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM + || mDragStartState == DragStartState.DRAGGED_INTENT ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness) : 2 * layout.stableInsets().top; // A Rect at the top of the screen that takes up the center 40%. - if (windowingMode == WINDOWING_MODE_FREEFORM) { + if (mDragStartState == DragStartState.FROM_FREEFORM) { final float toFullscreenScale = mContext.getResources().getFloat( R.dimen.desktop_mode_fullscreen_region_scale); final float toFullscreenWidth = (layout.width() * toFullscreenScale); @@ -153,9 +186,11 @@ public class DesktopModeVisualIndicator { (int) ((layout.width() / 2f) + (toFullscreenWidth / 2f)), transitionHeight)); } - // A screen-wide Rect if the task is in fullscreen or split. - if (windowingMode == WINDOWING_MODE_FULLSCREEN - || windowingMode == WINDOWING_MODE_MULTI_WINDOW) { + // A screen-wide Rect if the task is in fullscreen, split, or a dragged intent. + if (mDragStartState == DragStartState.FROM_FULLSCREEN + || mDragStartState == DragStartState.FROM_SPLIT + || mDragStartState == DragStartState.DRAGGED_INTENT + ) { region.union(new Rect(0, -captionHeight, layout.width(), @@ -166,12 +201,11 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateToDesktopRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, Region splitLeftRegion, Region splitRightRegion, Region toFullscreenRegion) { final Region region = new Region(); // If in desktop, we need no region. Otherwise it's the same for all windowing modes. - if (windowingMode != WINDOWING_MODE_FREEFORM) { + if (mDragStartState != DragStartState.FROM_FREEFORM) { region.union(new Rect(0, 0, layout.width(), layout.height())); region.op(splitLeftRegion, Region.Op.DIFFERENCE); region.op(splitRightRegion, Region.Op.DIFFERENCE); @@ -182,11 +216,10 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateSplitLeftRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int transitionEdgeWidth, int captionHeight) { final Region region = new Region(); // In freeform, keep the top corners clear. - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_split_from_desktop_height) : -captionHeight; @@ -196,11 +229,10 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateSplitRightRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int transitionEdgeWidth, int captionHeight) { final Region region = new Region(); // In freeform, keep the top corners clear. - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_split_from_desktop_height) : -captionHeight; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index f54b44b29683..33794d242c03 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -34,10 +34,12 @@ import android.graphics.Point import android.graphics.PointF import android.graphics.Rect import android.graphics.Region +import android.os.Binder import android.os.IBinder import android.os.SystemProperties import android.util.Size import android.view.Display.DEFAULT_DISPLAY +import android.view.DragEvent import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_NONE @@ -67,10 +69,9 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener +import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController @@ -79,6 +80,7 @@ import com.android.wm.shell.recents.RecentTasksController import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.TransitionUtil +import com.android.wm.shell.shared.ShellSharedConstants import com.android.wm.shell.shared.annotations.ExternalThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeFlags @@ -86,12 +88,13 @@ import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVI import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE 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.ShellSharedConstants import com.android.wm.shell.transition.OneShotRemoteHandler import com.android.wm.shell.transition.Transitions import com.android.wm.shell.windowdecor.DragPositioningCallbackUtility @@ -121,6 +124,7 @@ class DesktopTasksController( private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, + private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler, private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler, private val taskRepository: DesktopModeTaskRepository, @@ -146,12 +150,6 @@ class DesktopTasksController( visualIndicator?.releaseVisualIndicator(t) visualIndicator = null } - private val taskVisibilityListener = - object : VisibleTasksListener { - override fun onTasksVisibilityChanged(displayId: Int, visibleTasksCount: Int) { - launchAdjacentController.launchAdjacentEnabled = visibleTasksCount == 0 - } - } private val dragToDesktopStateListener = object : DragToDesktopStateListener { override fun onCommitToDesktopAnimationStart(tx: SurfaceControl.Transaction) { @@ -176,6 +174,9 @@ class DesktopTasksController( private var recentsAnimationRunning = false private lateinit var splitScreenController: SplitScreenController + // Launch cookie used to identify a drag and drop transition to fullscreen after it has begun. + // Used to prevent handleRequest from moving the new fullscreen task to freeform. + private var dragAndDropFullscreenCookie: Binder? = null init { desktopMode = DesktopModeImpl() @@ -194,7 +195,6 @@ class DesktopTasksController( this ) transitions.addHandler(this) - taskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor) dragToDesktopTransitionHandler.dragToDesktopStateListener = dragToDesktopStateListener recentsTransitionHandler.addTransitionStateListener( object : RecentsTransitionStateListener { @@ -858,6 +858,7 @@ class DesktopTasksController( val triggerTask = request.triggerTask var shouldHandleMidRecentsFreeformLaunch = recentsAnimationRunning && isFreeformRelaunch(triggerTask, request) + val isDragAndDropFullscreenTransition = taskContainsDragAndDropCookie(triggerTask) val shouldHandleRequest = when { // Handle freeform relaunch during recents animation @@ -866,6 +867,13 @@ class DesktopTasksController( reason = "recents animation is running" false } + // Don't handle request if this was a tear to fullscreen transition. + // handleFullscreenTaskLaunch moves fullscreen intents to freeform; + // this is an exception to the rule + isDragAndDropFullscreenTransition -> { + dragAndDropFullscreenCookie = null + false + } // Handle task closing for the last window if wallpaper is available shouldHandleTaskClosing(request) -> true // Only handle open or to front transitions @@ -884,8 +892,7 @@ class DesktopTasksController( false } // Only handle fullscreen or freeform tasks - triggerTask.windowingMode != WINDOWING_MODE_FULLSCREEN && - triggerTask.windowingMode != WINDOWING_MODE_FREEFORM -> { + !triggerTask.isFullscreen && !triggerTask.isFreeform -> { reason = "windowingMode not handled (${triggerTask.windowingMode})" false } @@ -920,6 +927,9 @@ class DesktopTasksController( return result } + private fun taskContainsDragAndDropCookie(taskInfo: RunningTaskInfo?) = + taskInfo?.launchCookies?.any { it == dragAndDropFullscreenCookie } ?: false + /** * Applies the proper surface states (rounded corners) to tasks when desktop mode is active. * This is intended to be used when desktop mode is part of another animation but isn't, itself, @@ -1045,6 +1055,17 @@ class DesktopTasksController( wct.reorder(task.token, true) return wct } + // If task is already visible, it must have been handled already and added to desktop mode. + // Cascade task only if it's not visible yet. + if (DesktopModeFlags.CASCADING_WINDOWS.isEnabled(context) + && !taskRepository.isVisibleTask(task.taskId)) { + val displayLayout = displayController.getDisplayLayout(task.displayId) + if (displayLayout != null) { + val initialBounds = Rect(task.configuration.windowConfiguration.bounds) + cascadeWindow(task, initialBounds, displayLayout) + wct.setBounds(task.token, initialBounds) + } + } if (useDesktopOverrideDensity()) { wct.setDensityDpi(task.token, DESKTOP_DENSITY_OVERRIDE) } @@ -1097,16 +1118,21 @@ class DesktopTasksController( /** Handle task closing by removing wallpaper activity if it's the last active task */ private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? { logV("handleTaskClosing") + if (!isDesktopModeShowing(task.displayId)) + return null + val wct = WindowContainerTransaction() if (taskRepository.isOnlyVisibleNonClosingTask(task.taskId) - && taskRepository.wallpaperActivityToken != null) { + && taskRepository.wallpaperActivityToken != null + ) { // Remove wallpaper activity when the last active task is removed removeWallpaperActivity(wct) } taskRepository.addClosingTask(task.displayId, task.taskId) // If a CLOSE or TO_BACK is triggered on a desktop task, remove the task. if (DesktopModeFlags.BACK_NAVIGATION.isEnabled(context) && - taskRepository.isVisibleTask(task.taskId)) { + taskRepository.isVisibleTask(task.taskId) + ) { wct.removeTask(task.token) } return if (wct.isEmpty) null else wct @@ -1134,18 +1160,9 @@ class DesktopTasksController( } if (DesktopModeFlags.CASCADING_WINDOWS.isEnabled(context)) { - val stableBounds = Rect() - displayLayout.getStableBoundsForDesktopMode(stableBounds) - - val activeTasks = taskRepository - .getActiveNonMinimizedOrderedTasks(taskInfo.displayId) - activeTasks.firstOrNull()?.let { activeTask -> - shellTaskOrganizer.getRunningTaskInfo(activeTask)?.let { - cascadeWindow(context.resources, stableBounds, - it.configuration.windowConfiguration.bounds, initialBounds) - } - } + cascadeWindow(taskInfo, initialBounds, displayLayout) } + if (canChangeTaskPosition(taskInfo)) { wct.setBounds(taskInfo.token, initialBounds) } @@ -1180,6 +1197,19 @@ class DesktopTasksController( } } + private fun cascadeWindow(task: TaskInfo, bounds: Rect, displayLayout: DisplayLayout) { + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + val activeTasks = taskRepository.getActiveNonMinimizedOrderedTasks(task.displayId) + activeTasks.firstOrNull()?.let { activeTask -> + shellTaskOrganizer.getRunningTaskInfo(activeTask)?.let { + cascadeWindow(context.resources, stableBounds, + it.configuration.windowConfiguration.bounds, bounds) + } + } + } + /** * Adds split screen changes to a transaction. Note that bounds are not reset here due to * animation; see {@link onDesktopSplitSelectAnimComplete} @@ -1299,15 +1329,17 @@ class DesktopTasksController( taskBounds: Rect ) { if (taskInfo.windowingMode != WINDOWING_MODE_FREEFORM) return - updateVisualIndicator(taskInfo, taskSurface, inputX, taskBounds.top.toFloat()) + updateVisualIndicator(taskInfo, taskSurface, inputX, taskBounds.top.toFloat(), + DragStartState.FROM_FREEFORM) } fun updateVisualIndicator( taskInfo: RunningTaskInfo, - taskSurface: SurfaceControl, + taskSurface: SurfaceControl?, inputX: Float, - taskTop: Float - ): IndicatorType { + taskTop: Float, + dragStartState: DragStartState + ): DesktopModeVisualIndicator.IndicatorType { // If the visual indicator does not exist, create it. val indicator = visualIndicator @@ -1317,10 +1349,11 @@ class DesktopTasksController( displayController, context, taskSurface, - rootTaskDisplayAreaOrganizer + rootTaskDisplayAreaOrganizer, + dragStartState ) if (visualIndicator == null) visualIndicator = indicator - return indicator.updateIndicatorType(PointF(inputX, taskTop), taskInfo.windowingMode) + return indicator.updateIndicatorType(PointF(inputX, taskTop)) } /** @@ -1353,7 +1386,6 @@ class DesktopTasksController( val indicatorType = indicator.updateIndicatorType( PointF(inputCoordinate.x, currentDragBounds.top.toFloat()), - taskInfo.windowingMode ) when (indicatorType) { IndicatorType.TO_FULLSCREEN_INDICATOR -> { @@ -1414,7 +1446,7 @@ class DesktopTasksController( // End the drag_hold CUJ interaction. interactionJankMonitor.end(CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD) val indicator = getVisualIndicator() ?: return IndicatorType.NO_INDICATOR - val indicatorType = indicator.updateIndicatorType(inputCoordinates, taskInfo.windowingMode) + val indicatorType = indicator.updateIndicatorType(inputCoordinates) when (indicatorType) { IndicatorType.TO_DESKTOP_INDICATOR -> { // Start a new jank interaction for the drag release to desktop window animation. @@ -1466,9 +1498,10 @@ class DesktopTasksController( taskRepository.setExclusionRegionListener(listener, callbackExecutor) } + // TODO(b/358114479): Move this implementation into a separate class. override fun onUnhandledDrag( launchIntent: PendingIntent, - dragSurface: SurfaceControl, + dragEvent: DragEvent, onFinishCallback: Consumer<Boolean> ): Boolean { // TODO(b/320797628): Pass through which display we are dropping onto @@ -1476,7 +1509,6 @@ class DesktopTasksController( // Not currently in desktop mode, ignore the drop return false } - val launchComponent = getComponent(launchIntent) if (!multiInstanceHelper.supportsMultiInstanceSplit(launchComponent)) { // TODO(b/320797628): Should only return early if there is an existing running task, and @@ -1484,20 +1516,69 @@ class DesktopTasksController( logV("Dropped intent does not support multi-instance") return false } - + val taskInfo = getFocusedFreeformTask(DEFAULT_DISPLAY) ?: return false + // TODO(b/358114479): Update drag and drop handling to give us visibility into when another + // window will accept a drag event. This way, we can hide the indicator when we won't + // be handling the transition here, allowing us to display the indicator accurately. + // For now, we create the indicator only on drag end and immediately dispose it. + val indicatorType = updateVisualIndicator(taskInfo, dragEvent.dragSurface, + dragEvent.x, dragEvent.y, + DragStartState.DRAGGED_INTENT) + releaseVisualIndicator() + val windowingMode = when (indicatorType) { + IndicatorType.TO_FULLSCREEN_INDICATOR -> { + WINDOWING_MODE_FULLSCREEN + } + IndicatorType.TO_SPLIT_LEFT_INDICATOR, + IndicatorType.TO_SPLIT_RIGHT_INDICATOR, + IndicatorType.TO_DESKTOP_INDICATOR + -> { + WINDOWING_MODE_FREEFORM + } + else -> error("Invalid indicator type: $indicatorType") + } + val displayLayout = displayController.getDisplayLayout(DEFAULT_DISPLAY) ?: return false + val newWindowBounds = Rect() + when (indicatorType) { + IndicatorType.TO_DESKTOP_INDICATOR -> { + // Use default bounds, but with the top-center at the drop point. + newWindowBounds.set(getDefaultDesktopTaskBounds(displayLayout)) + newWindowBounds.offsetTo( + dragEvent.x.toInt() - (newWindowBounds.width() / 2), + dragEvent.y.toInt() + ) + } + IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { + newWindowBounds.set(getSnapBounds(taskInfo, SnapPosition.RIGHT)) + } + IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { + newWindowBounds.set(getSnapBounds(taskInfo, SnapPosition.LEFT)) + } + else -> { + // Use empty bounds for the fullscreen case. + } + } // Start a new transition to launch the app val opts = ActivityOptions.makeBasic().apply { - launchWindowingMode = WINDOWING_MODE_FREEFORM + launchWindowingMode = windowingMode + launchBounds = newWindowBounds + pendingIntentBackgroundActivityStartMode = + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS pendingIntentLaunchFlags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK - setPendingIntentBackgroundActivityStartMode( - ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED - ) } + if (windowingMode == WINDOWING_MODE_FULLSCREEN) { + dragAndDropFullscreenCookie = Binder() + opts.launchCookie = dragAndDropFullscreenCookie + } val wct = WindowContainerTransaction() wct.sendPendingIntent(launchIntent, null, opts.toBundle()) - transitions.startTransition(TRANSIT_OPEN, wct, null /* handler */) + if (windowingMode == WINDOWING_MODE_FREEFORM) { + desktopModeDragAndDropTransitionHandler.handleDropEvent(wct) + } else { + transitions.startTransition(TRANSIT_OPEN, wct, null) + } // Report that this is handled by the listener onFinishCallback.accept(true) @@ -1505,7 +1586,7 @@ class DesktopTasksController( // We've assumed responsibility of cleaning up the drag surface, so do that now // TODO(b/320797628): Do an actual animation here for the drag surface val t = SurfaceControl.Transaction() - t.remove(dragSurface) + t.remove(dragEvent.dragSurface) t.apply() return true } @@ -1513,6 +1594,7 @@ class DesktopTasksController( private fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " pw.println("${prefix}DesktopTasksController") + DesktopModeStatus.dump(pw, innerPrefix, context) taskRepository.dump(pw, innerPrefix) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt index 9874f4c269a4..1a103d345ca7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt @@ -35,13 +35,13 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.animation.FloatProperties -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.shared.TransitionUtil import com.android.wm.shell.shared.animation.PhysicsAnimator +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt index be67a40560aa..24a7d77c983f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ReturnToDragStartAnimator.kt @@ -19,23 +19,27 @@ package com.android.wm.shell.desktopmode import android.animation.Animator import android.animation.RectEvaluator import android.animation.ValueAnimator +import android.content.Context import android.graphics.Rect import android.view.SurfaceControl +import android.widget.Toast import androidx.core.animation.addListener import com.android.internal.jank.InteractionJankMonitor +import com.android.wm.shell.R import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener import java.util.function.Supplier /** Animates the task surface moving from its current drag position to its pre-drag position. */ class ReturnToDragStartAnimator( + private val context: Context, private val transactionSupplier: Supplier<SurfaceControl.Transaction>, private val interactionJankMonitor: InteractionJankMonitor ) { private var boundsAnimator: Animator? = null private lateinit var taskRepositionAnimationListener: OnTaskRepositionAnimationListener - constructor(interactionJankMonitor: InteractionJankMonitor) : - this(Supplier { SurfaceControl.Transaction() }, interactionJankMonitor) + constructor(context: Context, interactionJankMonitor: InteractionJankMonitor) : + this(context, Supplier { SurfaceControl.Transaction() }, interactionJankMonitor) /** Sets a listener for the start and end of the reposition animation. */ fun setTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) { @@ -76,7 +80,11 @@ class ReturnToDragStartAnimator( .apply() taskRepositionAnimationListener.onAnimationEnd(taskId) boundsAnimator = null - // TODO(b/354658237) - show toast with relevant string + Toast.makeText( + context, + R.string.desktop_mode_non_resizable_snap_text, + Toast.LENGTH_SHORT + ).show() // TODO(b/339582583) - add Jank CUJ using interactionJankMonitor } ) 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 e00353d6ac82..cf02fb5fde8e 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 @@ -32,7 +32,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -70,6 +70,7 @@ import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.annotations.ExternalMainThread; +import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; @@ -127,7 +128,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll * drag. */ default boolean onUnhandledDrag(@NonNull PendingIntent launchIntent, - @NonNull SurfaceControl dragSurface, + @NonNull DragEvent dragEvent, @NonNull Consumer<Boolean> onFinishCallback) { return false; } @@ -329,9 +330,18 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll return false; } + DragSession dragSession = null; if (event.getAction() == ACTION_DRAG_STARTED) { mActiveDragDisplay = displayId; - pd.isHandlingDrag = DragUtils.canHandleDrag(event); + dragSession = new DragSession(ActivityTaskManager.getInstance(), + mDisplayController.getDisplayLayout(displayId), event.getClipData(), + event.getDragFlags()); + dragSession.initialize(); + final ActivityManager.RunningTaskInfo taskInfo = dragSession.runningTaskInfo; + // Desktop tasks will have their own drag handling. + final boolean isDesktopDrag = taskInfo != null && taskInfo.isFreeform() + && DesktopModeStatus.canEnterDesktopMode(mContext); + pd.isHandlingDrag = DragUtils.canHandleDrag(event) && !isDesktopDrag; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Clip description: handlingDrag=%b itemCount=%d mimeTypes=%s flags=%s", pd.isHandlingDrag, event.getClipData().getItemCount(), @@ -349,10 +359,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll Slog.w(TAG, "Unexpected drag start during an active drag"); return false; } - pd.dragSession = new DragSession(ActivityTaskManager.getInstance(), - mDisplayController.getDisplayLayout(displayId), event.getClipData(), - event.getDragFlags()); - pd.dragSession.initialize(); + pd.dragSession = dragSession; pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); if (pd.dragSession.hideDragSourceTaskId != -1) { @@ -437,7 +444,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll } final boolean handled = notifyListeners( - l -> l.onUnhandledDrag(launchIntent, dragEvent.getDragSurface(), onFinishCallback)); + l -> l.onUnhandledDrag(launchIntent, dragEvent, onFinishCallback)); if (!handled) { // Nobody handled this, we still have to notify WM onFinishCallback.accept(false); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java index 7e0362475f21..6fec0c1c20bc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java @@ -32,15 +32,15 @@ import static android.content.Intent.EXTRA_USER; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; -import static com.android.wm.shell.draganddrop.DragAndDropConstants.EXTRA_DISALLOW_HIT_REGION; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; +import static com.android.wm.shell.shared.draganddrop.DragAndDropConstants.EXTRA_DISALLOW_HIT_REGION; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import android.app.ActivityOptions; import android.app.ActivityTaskManager; @@ -69,8 +69,8 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreenController; import java.lang.annotation.Retention; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index d03a561cd3ea..3fecbe7fff74 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -21,15 +21,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS; import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -61,9 +60,9 @@ import com.android.internal.logging.InstanceId; import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.split.SplitScreenUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.splitscreen.SplitScreenController; import java.io.PrintWriter; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java index 18cd2d84d32d..f9749ec1e2b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java @@ -16,10 +16,9 @@ package com.android.wm.shell.draganddrop; -import static com.android.wm.shell.animation.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.wm.shell.shared.animation.Interpolators.FAST_OUT_SLOW_IN; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; 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 456767a1c9af..83cc18baf6cc 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 @@ -27,6 +27,7 @@ import android.view.SurfaceControl; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; @@ -49,6 +50,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, private final ShellTaskOrganizer mShellTaskOrganizer; private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository; private final WindowDecorViewModel mWindowDecorationViewModel; + private final LaunchAdjacentController mLaunchAdjacentController; private final SparseArray<State> mTasks = new SparseArray<>(); @@ -62,11 +64,13 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorationViewModel) { mContext = context; mShellTaskOrganizer = shellTaskOrganizer; mWindowDecorationViewModel = windowDecorationViewModel; mDesktopModeTaskRepository = desktopModeTaskRepository; + mLaunchAdjacentController = launchAdjacentController; if (shellInit != null) { shellInit.addInitCallback(this::onInit, this); } @@ -106,6 +110,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, } }); } + updateLaunchAdjacentController(); } @Override @@ -123,6 +128,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, if (!Transitions.ENABLE_SHELL_TRANSITIONS) { mWindowDecorationViewModel.destroyWindowDecoration(taskInfo); } + updateLaunchAdjacentController(); } @Override @@ -144,6 +150,17 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, taskInfo.isVisible); }); } + updateLaunchAdjacentController(); + } + + private void updateLaunchAdjacentController() { + for (int i = 0; i < mTasks.size(); i++) { + if (mTasks.valueAt(i).mTaskInfo.isVisible) { + mLaunchAdjacentController.setLaunchAdjacentEnabled(false); + return; + } + } + mLaunchAdjacentController.setLaunchAdjacentEnabled(true); } @Override 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 962309f7c534..1827923aad90 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 @@ -23,7 +23,7 @@ import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE; import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING; import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING; import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED; import android.annotation.BinderThread; import android.content.ComponentName; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 852382ddfba1..b0c896fbe516 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -40,9 +40,9 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.IconProvider; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.transition.Transitions; import java.lang.annotation.Retention; 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 86777dfb3d6b..b3beb4ab79c1 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 @@ -25,8 +25,6 @@ import static android.util.RotationUtils.rotateBounds; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP; import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS; import static com.android.wm.shell.pip.PipAnimationController.FRACTION_START; @@ -42,6 +40,8 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection; import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection; import static com.android.wm.shell.pip.PipAnimationController.isRemovePipDirection; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP; import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT; @@ -76,7 +76,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.ShellExecutor; @@ -90,6 +89,7 @@ import com.android.wm.shell.common.pip.PipUiEventLogger; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.transition.Transitions; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 37e2fd0a6867..7ba6ec452b83 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -290,6 +290,20 @@ public class PipTransition extends PipTransitionController { // Entering PIP. if (isEnteringPip(info)) { + if (!mPipTransitionState.isInPip() && TransitionUtil.hasDisplayChange(info)) { + final TransitionInfo.Change pipChange = getPipChange(info); + if (pipChange != null) { + // Clear old crop. + updatePipForUnhandledTransition(pipChange, startTransaction, finishTransaction); + } + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "%s: ignore exited PiP with display change", TAG); + // This should be an exited pip. E.g. a display change transition happens when + // the exiting pip is animating, then mergeAnimation -> end -> onFinishResize -> + // onExitPipFinished was called, i.e. pip state is UNDEFINED. So do not handle + // the incoming transition as entering pip. + return false; + } if (handleEnteringPipWithDisplayChange(transition, info, startTransaction, finishTransaction, finishCallback)) { // The destination position is applied directly and let default transition handler 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 da6221efdaee..5ec0c11109a0 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 @@ -32,7 +32,7 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE; import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; import android.app.ActivityManager; import android.app.ActivityTaskManager; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java index f92938989637..0d2b8e70422d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java @@ -37,8 +37,8 @@ import com.android.wm.shell.bubbles.DismissViewUtils; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.bubbles.DismissCircleView; import com.android.wm.shell.common.bubbles.DismissView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.android.wm.shell.common.pip.PipUiEventLogger; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import kotlin.Unit; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java index 0d7f7f66032a..c8b52c6b00c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java @@ -63,11 +63,11 @@ import android.widget.LinearLayout; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.pip.PipUiEventLogger; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index 999ab95ccb1e..82fbfadc162a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -39,7 +39,6 @@ import com.android.wm.shell.R; import com.android.wm.shell.animation.FloatProperties; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.android.wm.shell.common.pip.PipAppOpsListener; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipPerfHintController; @@ -49,6 +48,7 @@ import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.animation.PhysicsAnimator; import com.android.wm.shell.shared.annotations.ShellMainThread; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import kotlin.Unit; import kotlin.jvm.functions.Function0; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java index dc21f82c326c..eb6caba0600c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java @@ -19,7 +19,7 @@ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_PIP; import android.app.ActivityManager; import android.app.PictureInPictureParams; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java index e7e797096c0e..e04178e6d58c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDismissTargetHandler.java @@ -37,8 +37,8 @@ import com.android.wm.shell.bubbles.DismissViewUtils; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.bubbles.DismissCircleView; import com.android.wm.shell.common.bubbles.DismissView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.android.wm.shell.common.pip.PipUiEventLogger; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import kotlin.Unit; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java index c54e4cd90f57..a29104c4aafd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java @@ -61,11 +61,11 @@ import android.widget.LinearLayout; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; -import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.pip.PipUiEventLogger; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.animation.Interpolators; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java index 83253c6006fb..218d456e9596 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java @@ -42,7 +42,6 @@ import com.android.internal.util.Preconditions; import com.android.wm.shell.R; import com.android.wm.shell.animation.FloatProperties; import com.android.wm.shell.common.FloatingContentCoordinator; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.android.wm.shell.common.pip.PipAppOpsListener; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; @@ -51,6 +50,7 @@ import com.android.wm.shell.common.pip.PipSnapAlgorithm; import com.android.wm.shell.pip2.animation.PipResizeAnimator; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import kotlin.Unit; import kotlin.jvm.functions.Function0; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index 846fa6268fc3..ed18712b283d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -119,7 +119,8 @@ public class PipTransition extends PipTransitionController implements PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm, PipScheduler pipScheduler, - PipTransitionState pipTransitionState) { + PipTransitionState pipTransitionState, + PipUiStateChangeController pipUiStateChangeController) { super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, pipBoundsAlgorithm); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipUiStateChangeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipUiStateChangeController.java new file mode 100644 index 000000000000..224016e6c9d4 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipUiStateChangeController.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip2.phone; + +import android.app.ActivityTaskManager; +import android.app.Flags; +import android.app.PictureInPictureUiState; +import android.os.Bundle; +import android.os.RemoteException; + +import androidx.annotation.Nullable; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.protolog.ProtoLog; +import com.android.wm.shell.protolog.ShellProtoLogGroup; + +import java.util.function.Consumer; + +/** + * Controller class manages the {@link android.app.PictureInPictureUiState} callbacks sent to app. + */ +public class PipUiStateChangeController implements + PipTransitionState.PipTransitionStateChangedListener { + + private final PipTransitionState mPipTransitionState; + + private Consumer<PictureInPictureUiState> mPictureInPictureUiStateConsumer; + + public PipUiStateChangeController(PipTransitionState pipTransitionState) { + mPipTransitionState = pipTransitionState; + mPipTransitionState.addPipTransitionStateChangedListener(this); + mPictureInPictureUiStateConsumer = pictureInPictureUiState -> { + try { + ActivityTaskManager.getService().onPictureInPictureUiStateChanged( + pictureInPictureUiState); + } catch (RemoteException | IllegalStateException e) { + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "Failed to send PictureInPictureUiState."); + } + }; + } + + @Override + public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, + @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) { + if (newState == PipTransitionState.SWIPING_TO_PIP) { + onIsTransitioningToPipUiStateChange(true /* isTransitioningToPip */); + } else if (newState == PipTransitionState.ENTERING_PIP + && !mPipTransitionState.isInSwipePipToHomeTransition()) { + onIsTransitioningToPipUiStateChange(true /* isTransitioningToPip */); + } else if (newState == PipTransitionState.ENTERED_PIP) { + onIsTransitioningToPipUiStateChange(false /* isTransitioningToPip */); + } + } + + @VisibleForTesting + void setPictureInPictureUiStateConsumer(Consumer<PictureInPictureUiState> consumer) { + mPictureInPictureUiStateConsumer = consumer; + } + + private void onIsTransitioningToPipUiStateChange(boolean isTransitioningToPip) { + if (Flags.enablePipUiStateCallbackOnEntering() + && mPictureInPictureUiStateConsumer != null) { + mPictureInPictureUiStateConsumer.accept(new PictureInPictureUiState.Builder() + .setTransitioningToPip(isTransitioningToPip) + .build()); + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index da7e03f465e9..2f0af8557538 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -19,7 +19,7 @@ package com.android.wm.shell.recents; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.pm.PackageManager.FEATURE_PC; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; import android.app.ActivityManager; import android.app.ActivityTaskManager; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index ad3f4f8c9beb..7a9eb1c582b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -29,7 +29,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION; import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS; import android.annotation.Nullable; 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 06c57bd7092d..a6233dc927a5 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 @@ -25,9 +25,9 @@ import android.os.Bundle; import android.window.RemoteTransition; import com.android.internal.logging.InstanceId; -import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.shared.annotations.ExternalThread; +import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import java.util.concurrent.Executor; 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 83f827ae54da..7e165afce7d4 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 @@ -27,16 +27,16 @@ import static android.view.Display.DEFAULT_DISPLAY; import static com.android.wm.shell.common.MultiInstanceHelper.getComponent; import static com.android.wm.shell.common.MultiInstanceHelper.getShortcutComponent; import static com.android.wm.shell.common.MultiInstanceHelper.samePackage; -import static com.android.wm.shell.common.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit; import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition; import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN; +import static com.android.wm.shell.shared.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -90,16 +90,16 @@ import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.SyncTransactionQueue; -import com.android.wm.shell.common.TransactionPool; -import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.common.split.SplitScreenUtils; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.draganddrop.DragAndDropController; 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.shared.TransactionPool; import com.android.wm.shell.shared.annotations.ExternalThread; +import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenShellCommandHandler.java index af11ebc515d7..e1b474d9804a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenShellCommandHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenShellCommandHandler.java @@ -16,7 +16,7 @@ package com.android.wm.shell.splitscreen; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_UNKNOWN; import com.android.wm.shell.sysui.ShellCommandHandler; 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 c1f603839ef6..840049412db4 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 @@ -21,12 +21,12 @@ import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; -import static com.android.wm.shell.animation.Interpolators.ALPHA_IN; -import static com.android.wm.shell.animation.Interpolators.ALPHA_OUT; -import static com.android.wm.shell.common.split.SplitScreenConstants.FADE_DURATION; -import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_IN; +import static com.android.wm.shell.shared.animation.Interpolators.ALPHA_OUT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FADE_DURATION; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString; @@ -47,9 +47,9 @@ import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.internal.protolog.ProtoLog; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitDecorManager; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.transition.OneShotRemoteHandler; import com.android.wm.shell.transition.Transitions; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java index a0bf843444df..27ded57b38d9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java @@ -32,8 +32,8 @@ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED_ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_DRAG; import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_LAUNCHER; import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_MULTI_INSTANCE; @@ -58,7 +58,7 @@ import android.util.Slog; import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.util.FrameworkStatsLog; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason; /** 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 9bf515933b22..0b5c75104f65 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 @@ -34,16 +34,16 @@ import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER; import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER; -import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; -import static com.android.wm.shell.common.split.SplitScreenConstants.splitPositionToString; import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition; import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.shared.TransitionUtil.isClosingType; import static com.android.wm.shell.shared.TransitionUtil.isOpeningType; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.splitPositionToString; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; @@ -125,16 +125,16 @@ import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.LaunchAdjacentController; 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.common.split.SplitDecorManager; import com.android.wm.shell.common.split.SplitLayout; -import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.common.split.SplitScreenUtils; import com.android.wm.shell.common.split.SplitWindowManager; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.TransitionUtil; +import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason; import com.android.wm.shell.transition.DefaultMixedHandler; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index f19eb3f8291e..99f3832192e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -22,9 +22,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_OPENING; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuController.java index e0f63940663a..bb2f60b64a4a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuController.java @@ -39,8 +39,8 @@ import android.view.WindowManagerGlobal; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.split.SplitScreenConstants; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.split.SplitScreenConstants; /** * Handles the interaction logic with the {@link TvSplitMenuView}. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuView.java index 88e9757a9b31..b758b531075a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitMenuView.java @@ -19,8 +19,8 @@ package com.android.wm.shell.splitscreen.tv; import static android.view.KeyEvent.ACTION_DOWN; import static android.view.KeyEvent.KEYCODE_BACK; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import android.content.Context; import android.util.AttributeSet; @@ -31,7 +31,7 @@ import android.widget.LinearLayout; import androidx.annotation.Nullable; import com.android.wm.shell.R; -import com.android.wm.shell.common.split.SplitScreenConstants; +import com.android.wm.shell.shared.split.SplitScreenConstants; /** * A View for the Menu Window. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java index b65e97899f3e..34681569a16c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java @@ -32,8 +32,8 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.StageCoordinator; import com.android.wm.shell.sysui.ShellCommandHandler; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java index 81ca48fa6b3d..4451ee887363 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java @@ -28,9 +28,9 @@ import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; -import com.android.wm.shell.common.TransactionPool; -import com.android.wm.shell.common.split.SplitScreenConstants; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.TransactionPool; +import com.android.wm.shell.shared.split.SplitScreenConstants; import com.android.wm.shell.splitscreen.StageCoordinator; import com.android.wm.shell.transition.Transitions; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java index edb5aba1e46b..42b8b73cfb80 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java @@ -29,7 +29,8 @@ import android.window.SplashScreenView; import com.android.internal.jank.InteractionJankMonitor; import com.android.wm.shell.R; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; +import com.android.wm.shell.shared.startingsurface.SplashScreenExitAnimationUtils; /** * Default animation for exiting the splash screen window. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 759f97f54a9e..b18feefe7eb3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -78,8 +78,8 @@ import com.android.internal.policy.PhoneWindow; import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.IconProvider; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.TransactionPool; import java.util.List; import java.util.function.Consumer; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 97a695f34cf7..fac3592896ea 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -46,8 +46,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.annotations.ShellSplashscreenThread; /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index fa084c585a59..7cb8e8aa7b49 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -23,7 +23,7 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN; import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_WINDOWLESS; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW; import android.app.ActivityManager.RunningTaskInfo; import android.app.TaskInfo; @@ -48,7 +48,7 @@ import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java index bad5baf24651..2a22d4dd0cb5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java @@ -36,7 +36,7 @@ import android.window.StartingWindowInfo; import android.window.TaskSnapshot; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; class WindowlessSnapshotWindowCreator { private static final int DEFAULT_FADEOUT_DURATION = 233; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java index 1a38449fa447..e1d760058711 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java @@ -36,7 +36,7 @@ import android.window.StartingWindowInfo; import android.window.StartingWindowRemovalInfo; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; class WindowlessSplashWindowCreator extends AbsSplashWindowCreator { 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 de6887a2173b..a9a4e1093392 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 @@ -18,8 +18,8 @@ package com.android.wm.shell.transition; import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; -import static android.app.ActivityOptions.ANIM_NONE; import static android.app.ActivityOptions.ANIM_FROM_STYLE; +import static android.app.ActivityOptions.ANIM_NONE; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_SCALE_UP; import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION; @@ -112,8 +112,8 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer; 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.TransactionPool; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.sysui.ShellInit; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java index 8cc7f212af25..30d7245436be 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; -import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.wm.shell.shared.TransitionUtil.isOpeningMode; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java index 391c5fe3473c..fd4d568326d0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java @@ -18,7 +18,7 @@ package com.android.wm.shell.transition; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.transition.DefaultMixedHandler.handoverTransitionLeashes; import static com.android.wm.shell.transition.MixedTransitionHelper.animateEnterPipFromSplit; import static com.android.wm.shell.transition.MixedTransitionHelper.animateKeyguard; 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 195882553602..0bf9d368ab74 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 @@ -47,7 +47,7 @@ import android.window.TransitionInfo; import com.android.internal.R; import com.android.internal.policy.TransitionAnimation; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import java.util.ArrayList; 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 c850ff87f5ff..68217c0cc98a 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 @@ -38,12 +38,12 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_NO_ANIMATION; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; -import static com.android.window.flags.Flags.ensureWallpaperInTransitions; import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary; +import static com.android.window.flags.Flags.ensureWallpaperInTransitions; import static com.android.window.flags.Flags.migratePredictiveBackTransition; +import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; import static com.android.wm.shell.shared.TransitionUtil.isClosingType; import static com.android.wm.shell.shared.TransitionUtil.isOpeningType; -import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; import android.annotation.NonNull; import android.annotation.Nullable; @@ -85,12 +85,12 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.keyguard.KeyguardTransitionHandler; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.IHomeTransitionListener; import com.android.wm.shell.shared.IShellTransitions; import com.android.wm.shell.shared.ShellTransitions; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.annotations.ExternalThread; import com.android.wm.shell.sysui.ShellCommandHandler; @@ -717,7 +717,11 @@ public class Transitions implements RemoteCallable<Transitions>, Log.e(TAG, "Got duplicate transitionReady for " + transitionToken); // The transition is already somewhere else in the pipeline, so just return here. t.apply(); - existing.mFinishT.merge(finishT); + if (existing.mFinishT != null) { + existing.mFinishT.merge(finishT); + } else { + existing.mFinishT = finishT; + } return; } // This usually means the system is in a bad state and may not recover; however, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldAnimationController.java index e6d35e83116b..2ca749c276e7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldAnimationController.java @@ -23,7 +23,7 @@ import android.util.SparseArray; import android.view.SurfaceControl; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener; import com.android.wm.shell.unfold.animation.UnfoldTaskAnimator; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java index 88bfebf9331e..f783b45589b3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java @@ -34,7 +34,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.protolog.ProtoLog; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java index bb5d54652460..d28287da83b6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java @@ -19,8 +19,8 @@ package com.android.wm.shell.unfold.animation; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; @@ -41,7 +41,7 @@ import android.view.WindowInsets; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.wm.shell.common.DisplayInsetsController; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener; import com.android.wm.shell.splitscreen.SplitScreenController; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java index 3e06d2d0e797..88b752822a20 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java @@ -19,7 +19,7 @@ import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; -import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; +import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; import java.util.Objects; 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 401b78df026a..231570f5d90e 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 @@ -19,6 +19,7 @@ package com.android.wm.shell.windowdecor; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize; +import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset; import android.annotation.NonNull; import android.annotation.SuppressLint; @@ -260,6 +261,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL setupRootView(); } + bindData(mResult.mRootView, taskInfo); + if (!isDragResizeable) { closeDragResizeListener(); return; @@ -286,7 +289,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL final Resources res = mResult.mRootView.getResources(); mDragResizeListener.setGeometry(new DragResizeWindowGeometry(0 /* taskCornerRadius */, new Size(mResult.mWidth, mResult.mHeight), getResizeEdgeHandleSize(mContext, res), - getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop); + getResizeHandleEdgeInset(res), getFineResizeCornerSize(res), + getLargeResizeCornerSize(res)), touchSlop); } /** @@ -305,6 +309,14 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL maximize.setOnClickListener(mOnCaptionButtonClickListener); } + private void bindData(View rootView, RunningTaskInfo taskInfo) { + final boolean isFullscreen = + taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FULLSCREEN; + rootView.findViewById(R.id.maximize_window) + .setBackgroundResource(isFullscreen ? R.drawable.decor_restore_button_dark + : R.drawable.decor_maximize_button_dark); + } + void setCaptionColor(int captionColor) { if (mResult.mRootView == null) { return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 8c8f205ca353..457b5112076e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -34,13 +34,13 @@ import static android.view.MotionEvent.ACTION_UP; import static android.view.WindowInsets.Type.statusBars; import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.annotation.NonNull; @@ -74,6 +74,7 @@ import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.View; +import android.widget.Toast; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; @@ -96,7 +97,6 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource; -import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition; @@ -105,6 +105,7 @@ import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.desktopmode.DesktopModeFlags; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; +import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -469,7 +470,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { if (!decoration.mTaskInfo.isResizeable && DesktopModeFlags.DISABLE_SNAP_RESIZE.isEnabled(mContext)) { - //TODO(b/354658237) - show toast with relevant string + Toast.makeText(mContext, + R.string.desktop_mode_non_resizable_snap_text, Toast.LENGTH_SHORT).show(); } else { mDesktopTasksController.snapToHalfScreen(decoration.mTaskInfo, decoration.mTaskInfo.configuration.windowConfiguration.getBounds(), @@ -1029,7 +1031,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } final boolean shouldStartTransitionDrag = relevantDecor.checkTouchEventInFocusedCaptionHandle(ev) - || Flags.enableAdditionalWindowsAboveStatusBar(); + || Flags.enableAdditionalWindowsAboveStatusBar(); if (dragFromStatusBarAllowed && shouldStartTransitionDrag) { mTransitionDragActive = true; } @@ -1037,8 +1039,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } case MotionEvent.ACTION_UP: { if (mTransitionDragActive) { + final DesktopModeVisualIndicator.DragStartState dragStartState = + DesktopModeVisualIndicator.DragStartState + .getDragStartState(relevantDecor.mTaskInfo); + if (dragStartState == null) return; mDesktopTasksController.updateVisualIndicator(relevantDecor.mTaskInfo, - relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY()); + relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY(), + dragStartState); mTransitionDragActive = false; if (mMoveToDesktopAnimator != null) { // Though this isn't a hover event, we need to update handle's hover state @@ -1078,10 +1085,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && mMoveToDesktopAnimator == null) { return; } + final DesktopModeVisualIndicator.DragStartState dragStartState = + DesktopModeVisualIndicator.DragStartState + .getDragStartState(relevantDecor.mTaskInfo); + if (dragStartState == null) return; final DesktopModeVisualIndicator.IndicatorType indicatorType = mDesktopTasksController.updateVisualIndicator( relevantDecor.mTaskInfo, - relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY()); + relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY(), + dragStartState); if (indicatorType != TO_FULLSCREEN_INDICATOR) { if (mMoveToDesktopAnimator == null) { mMoveToDesktopAnimator = new MoveToDesktopAnimator( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 538d0fb9cbf6..75a6cd7b720e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -27,10 +27,11 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.icons.BaseIconFactory.MODE_DEFAULT; import static com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize; import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize; +import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset; import android.annotation.NonNull; import android.annotation.Nullable; @@ -515,8 +516,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin if (mDragResizeListener.setGeometry( new DragResizeWindowGeometry(mRelayoutParams.mCornerRadius, new Size(mResult.mWidth, mResult.mHeight), - getResizeEdgeHandleSize(mContext, res), getFineResizeCornerSize(res), - getLargeResizeCornerSize(res)), touchSlop) + getResizeEdgeHandleSize(mContext, res), getResizeHandleEdgeInset(res), + getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop) || !mTaskInfo.positionInParent.equals(mPositionInParent)) { updateExclusionRegion(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java index 0f2de700d3ae..cb9781e86c87 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java @@ -82,32 +82,26 @@ public class DragPositioningCallbackUtility { final int oldRight = repositionTaskBounds.right; final int oldBottom = repositionTaskBounds.bottom; - repositionTaskBounds.set(taskBoundsAtDragStart); // Make sure the new resizing destination in any direction falls within the stable bounds. - // If not, set the bounds back to the old location that was valid to avoid conflicts with - // some regions such as the gesture area. if ((ctrlType & CTRL_TYPE_LEFT) != 0) { - final int candidateLeft = repositionTaskBounds.left + (int) delta.x; - repositionTaskBounds.left = (candidateLeft > stableBounds.left) - ? candidateLeft : oldLeft; + repositionTaskBounds.left = Math.max(repositionTaskBounds.left + (int) delta.x, + stableBounds.left); } if ((ctrlType & CTRL_TYPE_RIGHT) != 0) { - final int candidateRight = repositionTaskBounds.right + (int) delta.x; - repositionTaskBounds.right = (candidateRight < stableBounds.right) - ? candidateRight : oldRight; + repositionTaskBounds.right = Math.min(repositionTaskBounds.right + (int) delta.x, + stableBounds.right); } if ((ctrlType & CTRL_TYPE_TOP) != 0) { - final int candidateTop = repositionTaskBounds.top + (int) delta.y; - repositionTaskBounds.top = (candidateTop > stableBounds.top) - ? candidateTop : oldTop; + repositionTaskBounds.top = Math.max(repositionTaskBounds.top + (int) delta.y, + stableBounds.top); } if ((ctrlType & CTRL_TYPE_BOTTOM) != 0) { - final int candidateBottom = repositionTaskBounds.bottom + (int) delta.y; - repositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom) - ? candidateBottom : oldBottom; + repositionTaskBounds.bottom = Math.min(repositionTaskBounds.bottom + (int) delta.y, + stableBounds.bottom); } + // If width or height are negative or exceeding the width or height constraints, revert the // respective bounds to use previous bound dimensions. if (isExceedingWidthConstraint(repositionTaskBounds, stableBounds, displayController, @@ -120,14 +114,12 @@ public class DragPositioningCallbackUtility { repositionTaskBounds.top = oldTop; repositionTaskBounds.bottom = oldBottom; } - // If there are no changes to the bounds after checking new bounds against minimum width - // and height, do not set bounds and return false - if (oldLeft == repositionTaskBounds.left && oldTop == repositionTaskBounds.top - && oldRight == repositionTaskBounds.right - && oldBottom == repositionTaskBounds.bottom) { - return false; - } - return true; + + // If there are no changes to the bounds after checking new bounds against minimum and + // maximum width and height, do not set bounds and return false + return oldLeft != repositionTaskBounds.left || oldTop != repositionTaskBounds.top + || oldRight != repositionTaskBounds.right + || oldBottom != repositionTaskBounds.bottom; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java index 014d61d00b9e..6dedf6da3ab7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java @@ -16,6 +16,7 @@ package com.android.wm.shell.windowdecor; +import static android.view.InputDevice.SOURCE_MOUSE; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.EDGE_DRAG_RESIZE; @@ -44,27 +45,32 @@ import java.util.Objects; final class DragResizeWindowGeometry { private final int mTaskCornerRadius; private final Size mTaskSize; - // The size of the handle applied to the edges of the window, for the user to drag resize. - private final int mResizeHandleThickness; + // The size of the handle outside the task window applied to the edges of the window, for the + // user to drag resize. + private final int mResizeHandleEdgeOutset; + // The size of the handle inside the task window applied to the edges of the window, for the + // user to drag resize. + private final int mResizeHandleEdgeInset; // The task corners to permit drag resizing with a course input, such as touch. - private final @NonNull TaskCorners mLargeTaskCorners; // The task corners to permit drag resizing with a fine input, such as stylus or cursor. private final @NonNull TaskCorners mFineTaskCorners; // The bounds for each edge drag region, which can resize the task in one direction. - private final @NonNull TaskEdges mTaskEdges; + final @NonNull TaskEdges mTaskEdges; DragResizeWindowGeometry(int taskCornerRadius, @NonNull Size taskSize, - int resizeHandleThickness, int fineCornerSize, int largeCornerSize) { + int resizeHandleEdgeOutset, int resizeHandleEdgeInset, int fineCornerSize, + int largeCornerSize) { mTaskCornerRadius = taskCornerRadius; mTaskSize = taskSize; - mResizeHandleThickness = resizeHandleThickness; + mResizeHandleEdgeOutset = resizeHandleEdgeOutset; + mResizeHandleEdgeInset = resizeHandleEdgeInset; mLargeTaskCorners = new TaskCorners(mTaskSize, largeCornerSize); mFineTaskCorners = new TaskCorners(mTaskSize, fineCornerSize); // Save touch areas for each edge. - mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleThickness); + mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleEdgeOutset, mResizeHandleEdgeInset); } /** @@ -72,11 +78,18 @@ final class DragResizeWindowGeometry { */ static int getResizeEdgeHandleSize(@NonNull Context context, @NonNull Resources res) { return EDGE_DRAG_RESIZE.isEnabled(context) - ? res.getDimensionPixelSize(R.dimen.desktop_mode_edge_handle) + ? res.getDimensionPixelSize(R.dimen.freeform_edge_handle_outset) : res.getDimensionPixelSize(R.dimen.freeform_resize_handle); } /** + * Returns the resource value to use for the edge resize handle inside the task bounds. + */ + static int getResizeHandleEdgeInset(@NonNull Resources res) { + return res.getDimensionPixelSize(R.dimen.freeform_edge_handle_inset); + } + + /** * Returns the resource value to use for course input, such as touch, that benefits from a large * square on each of the window's corners. */ @@ -95,7 +108,8 @@ final class DragResizeWindowGeometry { /** * Returns the size of the task this geometry is calculated for. */ - @NonNull Size getTaskSize() { + @NonNull + Size getTaskSize() { // Safe to return directly since size is immutable. return mTaskSize; } @@ -153,7 +167,10 @@ final class DragResizeWindowGeometry { static boolean isEdgeResizePermitted(@NonNull Context context, @NonNull MotionEvent e) { if (EDGE_DRAG_RESIZE.isEnabled(context)) { return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS - || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; + || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE + // Touchpad input + || (e.isFromSource(SOURCE_MOUSE) + && e.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER); } else { return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; } @@ -217,13 +234,15 @@ final class DragResizeWindowGeometry { ctrlType |= CTRL_TYPE_BOTTOM; } // If the touch is within one of the four corners, check if it is within the bounds of the - // // handle. + // handle. if ((ctrlType & (CTRL_TYPE_LEFT | CTRL_TYPE_RIGHT)) != 0 && (ctrlType & (CTRL_TYPE_TOP | CTRL_TYPE_BOTTOM)) != 0) { return checkDistanceFromCenter(ctrlType, x, y); } - // Otherwise, we should make sure we don't resize tasks inside task bounds. - return (x < 0 || y < 0 || x >= mTaskSize.getWidth() || y >= mTaskSize.getHeight()) + // Allow a small resize handle inside the task bounds defined by the edge inset. + return (x <= mResizeHandleEdgeInset || y <= mResizeHandleEdgeInset + || x >= mTaskSize.getWidth() - mResizeHandleEdgeInset + || y >= mTaskSize.getHeight() - mResizeHandleEdgeInset) ? ctrlType : CTRL_TYPE_UNDEFINED; } @@ -237,7 +256,7 @@ final class DragResizeWindowGeometry { final Point cornerRadiusCenter = calculateCenterForCornerRadius(ctrlType); double distanceFromCenter = Math.hypot(x - cornerRadiusCenter.x, y - cornerRadiusCenter.y); - if (distanceFromCenter < mTaskCornerRadius + mResizeHandleThickness + if (distanceFromCenter < mTaskCornerRadius + mResizeHandleEdgeOutset && distanceFromCenter >= mTaskCornerRadius) { return ctrlType; } @@ -288,7 +307,8 @@ final class DragResizeWindowGeometry { return this.mTaskCornerRadius == other.mTaskCornerRadius && this.mTaskSize.equals(other.mTaskSize) - && this.mResizeHandleThickness == other.mResizeHandleThickness + && this.mResizeHandleEdgeOutset == other.mResizeHandleEdgeOutset + && this.mResizeHandleEdgeInset == other.mResizeHandleEdgeInset && this.mFineTaskCorners.equals(other.mFineTaskCorners) && this.mLargeTaskCorners.equals(other.mLargeTaskCorners) && this.mTaskEdges.equals(other.mTaskEdges); @@ -299,7 +319,8 @@ final class DragResizeWindowGeometry { return Objects.hash( mTaskCornerRadius, mTaskSize, - mResizeHandleThickness, + mResizeHandleEdgeOutset, + mResizeHandleEdgeInset, mFineTaskCorners, mLargeTaskCorners, mTaskEdges); @@ -421,26 +442,27 @@ final class DragResizeWindowGeometry { private final @NonNull Rect mBottomEdgeBounds; private final @NonNull Region mRegion; - private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness) { + private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness, + int resizeHandleEdgeInset) { // Save touch areas for each edge. mTopEdgeBounds = new Rect( -resizeHandleThickness, -resizeHandleThickness, taskSize.getWidth() + resizeHandleThickness, - 0); + resizeHandleThickness); mLeftEdgeBounds = new Rect( -resizeHandleThickness, 0, - 0, + resizeHandleEdgeInset, taskSize.getHeight()); mRightEdgeBounds = new Rect( - taskSize.getWidth(), + taskSize.getWidth() - resizeHandleEdgeInset, 0, taskSize.getWidth() + resizeHandleThickness, taskSize.getHeight()); mBottomEdgeBounds = new Rect( -resizeHandleThickness, - taskSize.getHeight(), + taskSize.getHeight() - resizeHandleEdgeInset, taskSize.getWidth() + resizeHandleThickness, taskSize.getHeight() + resizeHandleThickness); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt index c16c16f5dfa2..34de94eb3352 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt @@ -45,7 +45,7 @@ import androidx.compose.ui.graphics.toArgb import androidx.core.view.isGone import com.android.window.flags.Flags import com.android.wm.shell.R -import com.android.wm.shell.common.split.SplitScreenConstants +import com.android.wm.shell.shared.split.SplitScreenConstants import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt index e3d22342cc9b..9590ccdc3b97 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt @@ -30,7 +30,7 @@ import android.widget.Button import androidx.core.animation.doOnEnd import androidx.core.view.children import com.android.wm.shell.R -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators /** Animates the Handle Menu opening. */ class HandleMenuAnimator( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt index 095d33736595..114c33114421 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt @@ -59,10 +59,10 @@ import androidx.compose.ui.graphics.toArgb import androidx.core.animation.addListener import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer -import com.android.wm.shell.animation.Interpolators.EMPHASIZED_DECELERATE -import com.android.wm.shell.animation.Interpolators.FAST_OUT_LINEAR_IN import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED_DECELERATE +import com.android.wm.shell.shared.animation.Interpolators.FAST_OUT_LINEAR_IN import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer import com.android.wm.shell.windowdecor.common.DecorThemeUtil import com.android.wm.shell.windowdecor.common.OPACITY_12 diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt index 753723cd73d6..510032ba4480 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt @@ -31,7 +31,7 @@ import android.view.WindowManager import android.widget.ImageButton import com.android.window.flags.Flags import com.android.wm.shell.R -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer /** diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt new file mode 100644 index 000000000000..5bc975bbd565 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.scenarios + +import android.platform.test.annotations.Postsubmit +import android.app.Instrumentation +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.ImeAppHelper +import com.android.server.wm.flicker.helpers.MailAppHelper +import com.android.server.wm.flicker.helpers.NewTasksAppHelper +import com.android.server.wm.flicker.helpers.SimpleAppHelper +import com.android.window.flags.Flags +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Assume +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class ResizeAppCornerMultiWindow +@JvmOverloads +constructor(val rotation: Rotation = Rotation.ROTATION_0, + val horizontalChange: Int = 50, + val verticalChange: Int = -50) { + + private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + private val tapl = LauncherInstrumentation() + private val wmHelper = WindowManagerStateHelper(instrumentation) + private val device = UiDevice.getInstance(instrumentation) + private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation)) + private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation)) + private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation)) + private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation)) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation) + + @Before + fun setup() { + Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) + tapl.setEnableRotation(true) + tapl.setExpectedRotation(rotation.value) + testApp.enterDesktopWithDrag(wmHelper, device) + mailApp.launchViaIntent(wmHelper) + newTasksApp.launchViaIntent(wmHelper) + imeApp.launchViaIntent(wmHelper) + } + + @Test + open fun resizeAppWithCornerResize() { + imeApp.cornerResize(wmHelper, + device, + DesktopModeAppHelper.Corners.RIGHT_TOP, + horizontalChange, + verticalChange) + } + + @After + fun teardown() { + testApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp index 35b2f56bca92..a231e381beda 100644 --- a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp +++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp @@ -15,6 +15,7 @@ // package { + default_team: "trendy_team_multitasking_windowing", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_base_license" @@ -30,6 +31,46 @@ filegroup { ], } +java_library { + name: "WMShellFlickerTestsSplitScreenBase", + srcs: [ + ":WMShellFlickerTestsSplitScreenBase-src", + ], + static_libs: [ + "WMShellFlickerTestsBase", + "wm-shell-flicker-utils", + "androidx.test.ext.junit", + "flickertestapplib", + "flickerlib", + "flickerlib-helpers", + "flickerlib-trace_processor_shell", + "platform-test-annotations", + "wm-flicker-common-app-helpers", + "wm-flicker-common-assertions", + "launcher-helper-lib", + "launcher-aosp-tapl", + ], +} + +android_test { + name: "WMShellFlickerTestsSplitScreen", + defaults: ["WMShellFlickerTestsDefault"], + manifest: "AndroidManifest.xml", + package_name: "com.android.wm.shell.flicker.splitscreen", + instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen", + test_config_template: "AndroidTestTemplate.xml", + srcs: ["src/**/*.kt"], + exclude_srcs: ["src/**/benchmark/*.kt"], + static_libs: [ + "WMShellFlickerTestsBase", + "WMShellFlickerTestsSplitScreenBase", + ], + data: ["trace_config/*"], +} + +//////////////////////////////////////////////////////////////////////////////// +// Begin cleanup after gcl merges + filegroup { name: "WMShellFlickerTestsSplitScreenGroup1-src", srcs: [ @@ -61,27 +102,6 @@ filegroup { ], } -java_library { - name: "WMShellFlickerTestsSplitScreenBase", - srcs: [ - ":WMShellFlickerTestsSplitScreenBase-src", - ], - static_libs: [ - "WMShellFlickerTestsBase", - "wm-shell-flicker-utils", - "androidx.test.ext.junit", - "flickertestapplib", - "flickerlib", - "flickerlib-helpers", - "flickerlib-trace_processor_shell", - "platform-test-annotations", - "wm-flicker-common-app-helpers", - "wm-flicker-common-assertions", - "launcher-helper-lib", - "launcher-aosp-tapl", - ], -} - android_test { name: "WMShellFlickerTestsSplitScreenGroup1", defaults: ["WMShellFlickerTestsDefault"], @@ -154,3 +174,156 @@ android_test { ], data: ["trace_config/*"], } + +//////////////////////////////////////////////////////////////////////////////// +// End cleanup after gcl merges + +//////////////////////////////////////////////////////////////////////////////// +// Begin breakdowns for FlickerTestsRotation module + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-CatchAll", + base: "WMShellFlickerTestsSplitScreen", + exclude_filters: [ + "com.android.wm.shell.flicker.splitscreen.CopyContentInSplit", + "com.android.wm.shell.flicker.splitscreen.DismissSplitScreenByDivider", + "com.android.wm.shell.flicker.splitscreen.DismissSplitScreenByGoHome", + "com.android.wm.shell.flicker.splitscreen.DragDividerToResize", + "com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromAllApps", + "com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromNotification", + "com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromShortcut", + "com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromTaskbar", + "com.android.wm.shell.flicker.splitscreen.EnterSplitScreenFromOverview", + "com.android.wm.shell.flicker.splitscreen.MultipleShowImeRequestsInSplitScreen", + "com.android.wm.shell.flicker.splitscreen.SwitchAppByDoubleTapDivider", + "com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromAnotherApp", + "com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromHome", + "com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromRecent", + "com.android.wm.shell.flicker.splitscreen.SwitchBetweenSplitPairs", + "com.android.wm.shell.flicker.splitscreen.SwitchBetweenSplitPairsNoPip", + "com.android.wm.shell.flicker.splitscreen.", + ], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-CopyContentInSplit", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.CopyContentInSplit"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-DismissSplitScreenByDivider", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.DismissSplitScreenByDivider"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-DismissSplitScreenByGoHome", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.DismissSplitScreenByGoHome"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-DragDividerToResize", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.DragDividerToResize"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-EnterSplitScreenByDragFromAllApps", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromAllApps"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-EnterSplitScreenByDragFromNotification", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromNotification"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-EnterSplitScreenByDragFromShortcut", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromShortcut"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-EnterSplitScreenByDragFromTaskbar", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.EnterSplitScreenByDragFromTaskbar"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-EnterSplitScreenFromOverview", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.EnterSplitScreenFromOverview"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-MultipleShowImeRequestsInSplitScreen", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.MultipleShowImeRequestsInSplitScreen"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchAppByDoubleTapDivider", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchAppByDoubleTapDivider"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchBackToSplitFromAnotherApp", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromAnotherApp"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchBackToSplitFromHome", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromHome"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchBackToSplitFromRecent", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchBackToSplitFromRecent"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchBetweenSplitPairs", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchBetweenSplitPairs"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-SwitchBetweenSplitPairsNoPip", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.SwitchBetweenSplitPairsNoPip"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsSplitScreen-UnlockKeyguardToSplitScreen", + base: "WMShellFlickerTestsSplitScreen", + include_filters: ["com.android.wm.shell.flicker.splitscreen.UnlockKeyguardToSplitScreen"], + test_suites: ["device-tests"], +} + +// End breakdowns for FlickerTestsRotation module +//////////////////////////////////////////////////////////////////////////////// diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp b/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp index e151ab2c5878..29a9f1050b25 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp @@ -15,6 +15,7 @@ // package { + default_team: "trendy_team_app_compat", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_base_license" @@ -23,6 +24,9 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +//////////////////////////////////////////////////////////////////////////////// +// Begin cleanup after gcl merge + filegroup { name: "WMShellFlickerTestsAppCompat-src", srcs: [ @@ -41,3 +45,80 @@ android_test { static_libs: ["WMShellFlickerTestsBase"], data: ["trace_config/*"], } + +//////////////////////////////////////////////////////////////////////////////// +// End cleanup after gcl merge + +android_test { + name: "WMShellFlickerTestsAppCompat", + defaults: ["WMShellFlickerTestsDefault"], + manifest: "AndroidManifest.xml", + package_name: "com.android.wm.shell.flicker", + instrumentation_target_package: "com.android.wm.shell.flicker", + test_config_template: "AndroidTestTemplate.xml", + srcs: ["src/**/*.kt"], + static_libs: ["WMShellFlickerTestsBase"], + data: ["trace_config/*"], +} + +//////////////////////////////////////////////////////////////////////////////// +// Begin breakdowns for WMShellFlickerTestsAppCompat module + +test_module_config { + name: "WMShellFlickerTestsAppCompat-CatchAll", + base: "WMShellFlickerTestsAppCompat", + exclude_filters: [ + "com.android.wm.shell.flicker.appcompat.OpenAppInSizeCompatModeTest", + "com.android.wm.shell.flicker.appcompat.OpenTransparentActivityTest", + "com.android.wm.shell.flicker.appcompat.QuickSwitchLauncherToLetterboxAppTest", + "com.android.wm.shell.flicker.appcompat.RepositionFixedPortraitAppTest", + "com.android.wm.shell.flicker.appcompat.RestartAppInSizeCompatModeTest", + "com.android.wm.shell.flicker.appcompat.RotateImmersiveAppInFullscreenTest", + ], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-OpenAppInSizeCompatModeTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.OpenAppInSizeCompatModeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-OpenTransparentActivityTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.OpenTransparentActivityTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-QuickSwitchLauncherToLetterboxAppTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.QuickSwitchLauncherToLetterboxAppTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-RepositionFixedPortraitAppTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.RepositionFixedPortraitAppTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-RestartAppInSizeCompatModeTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.RestartAppInSizeCompatModeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsAppCompat-RotateImmersiveAppInFullscreenTest", + base: "WMShellFlickerTestsAppCompat", + include_filters: ["com.android.wm.shell.flicker.appcompat.RotateImmersiveAppInFullscreenTest"], + test_suites: ["device-tests"], +} + +// End breakdowns for FlickerTestsRotation module +//////////////////////////////////////////////////////////////////////////////// diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/Android.bp b/libs/WindowManager/Shell/tests/flicker/bubble/Android.bp index f0b4f1faad46..2ff7ab231c28 100644 --- a/libs/WindowManager/Shell/tests/flicker/bubble/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/bubble/Android.bp @@ -15,6 +15,7 @@ // package { + default_team: "trendy_team_multitasking_windowing", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_base_license" @@ -34,3 +35,57 @@ android_test { static_libs: ["WMShellFlickerTestsBase"], data: ["trace_config/*"], } + +//////////////////////////////////////////////////////////////////////////////// +// Begin breakdowns for WMShellFlickerTestsBubbles module + +test_module_config { + name: "WMShellFlickerTestsBubbles-CatchAll", + base: "WMShellFlickerTestsBubbles", + exclude_filters: [ + "com.android.wm.shell.flicker.bubble.ChangeActiveActivityFromBubbleTest", + "com.android.wm.shell.flicker.bubble.DragToDismissBubbleScreenTest", + "com.android.wm.shell.flicker.bubble.OpenActivityFromBubbleOnLocksreenTest", + "com.android.wm.shell.flicker.bubble.OpenActivityFromBubbleTest", + "com.android.wm.shell.flicker.bubble.SendBubbleNotificationTest", + ], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsBubbles-ChangeActiveActivityFromBubbleTest", + base: "WMShellFlickerTestsBubbles", + include_filters: ["com.android.wm.shell.flicker.bubble.ChangeActiveActivityFromBubbleTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsBubbles-DragToDismissBubbleScreenTest", + base: "WMShellFlickerTestsBubbles", + include_filters: ["com.android.wm.shell.flicker.bubble.DragToDismissBubbleScreenTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsBubbles-OpenActivityFromBubbleOnLocksreenTest", + base: "WMShellFlickerTestsBubbles", + include_filters: ["com.android.wm.shell.flicker.bubble.OpenActivityFromBubbleOnLocksreenTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsBubbles-OpenActivityFromBubbleTest", + base: "WMShellFlickerTestsBubbles", + include_filters: ["com.android.wm.shell.flicker.bubble.OpenActivityFromBubbleTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsBubbles-SendBubbleNotificationTest", + base: "WMShellFlickerTestsBubbles", + include_filters: ["com.android.wm.shell.flicker.bubble.SendBubbleNotificationTest"], + test_suites: ["device-tests"], +} + +// End breakdowns for WMShellFlickerTestsBubbles module +//////////////////////////////////////////////////////////////////////////////// diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp index faeb342a44be..4165ed093929 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp @@ -15,6 +15,7 @@ // package { + default_team: "trendy_team_multitasking_windowing", // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_base_license" @@ -24,6 +25,14 @@ package { } filegroup { + name: "WMShellFlickerTestsPipApps-src", + srcs: ["src/**/apps/*.kt"], +} + +//////////////////////////////////////////////////////////////////////////////// +// Begin cleanup after gcl merges + +filegroup { name: "WMShellFlickerTestsPip1-src", srcs: [ "src/**/A*.kt", @@ -52,11 +61,6 @@ filegroup { srcs: ["src/**/common/*.kt"], } -filegroup { - name: "WMShellFlickerTestsPipApps-src", - srcs: ["src/**/apps/*.kt"], -} - android_test { name: "WMShellFlickerTestsPip1", defaults: ["WMShellFlickerTestsDefault"], @@ -107,6 +111,21 @@ android_test { data: ["trace_config/*"], } +//////////////////////////////////////////////////////////////////////////////// +// End cleanup after gcl merges + +android_test { + name: "WMShellFlickerTestsPip", + defaults: ["WMShellFlickerTestsDefault"], + manifest: "AndroidManifest.xml", + package_name: "com.android.wm.shell.flicker.pip", + instrumentation_target_package: "com.android.wm.shell.flicker.pip", + test_config_template: "AndroidTestTemplate.xml", + srcs: ["src/**/*.kt"], + static_libs: ["WMShellFlickerTestsBase"], + data: ["trace_config/*"], +} + android_test { name: "WMShellFlickerTestsPipApps", defaults: ["WMShellFlickerTestsDefault"], @@ -146,3 +165,185 @@ csuite_test { test_plan_include: "csuitePlan.xml", test_config_template: "csuiteDefaultTemplate.xml", } + +//////////////////////////////////////////////////////////////////////////////// +// Begin breakdowns for WMShellFlickerTestsPip module + +test_module_config { + name: "WMShellFlickerTestsPip-CatchAll", + base: "WMShellFlickerTestsPip", + exclude_filters: [ + "com.android.wm.shell.flicker.pip.AutoEnterPipOnGoToHomeTest", + "com.android.wm.shell.flicker.pip.AutoEnterPipWithSourceRectHintTest", + "com.android.wm.shell.flicker.pip.ClosePipBySwipingDownTest", + "com.android.wm.shell.flicker.pip.ClosePipWithDismissButtonTest", + "com.android.wm.shell.flicker.pip.EnterPipOnUserLeaveHintTest", + "com.android.wm.shell.flicker.pip.EnterPipViaAppUiButtonTest", + "com.android.wm.shell.flicker.pip.ExitPipToAppViaExpandButtonTest", + "com.android.wm.shell.flicker.pip.ExitPipToAppViaIntentTest", + "com.android.wm.shell.flicker.pip.ExpandPipOnDoubleClickTest", + "com.android.wm.shell.flicker.pip.ExpandPipOnPinchOpenTest", + "com.android.wm.shell.flicker.pip.FromSplitScreenAutoEnterPipOnGoToHomeTest", + "com.android.wm.shell.flicker.pip.FromSplitScreenEnterPipOnUserLeaveHintTest", + "com.android.wm.shell.flicker.pip.MovePipDownOnShelfHeightChange", + "com.android.wm.shell.flicker.pip.MovePipOnImeVisibilityChangeTest", + "com.android.wm.shell.flicker.pip.MovePipUpOnShelfHeightChangeTest", + "com.android.wm.shell.flicker.pip.PipAspectRatioChangeTest", + "com.android.wm.shell.flicker.pip.PipDragTest", + "com.android.wm.shell.flicker.pip.PipDragThenSnapTest", + "com.android.wm.shell.flicker.pip.PipPinchInTest", + "com.android.wm.shell.flicker.pip.SetRequestedOrientationWhilePinned", + "com.android.wm.shell.flicker.pip.ShowPipAndRotateDisplay", + ], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-AutoEnterPipOnGoToHomeTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.AutoEnterPipOnGoToHomeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-AutoEnterPipWithSourceRectHintTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.AutoEnterPipWithSourceRectHintTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ClosePipBySwipingDownTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ClosePipBySwipingDownTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ClosePipWithDismissButtonTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ClosePipWithDismissButtonTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-EnterPipOnUserLeaveHintTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.EnterPipOnUserLeaveHintTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-EnterPipViaAppUiButtonTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.EnterPipViaAppUiButtonTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ExitPipToAppViaExpandButtonTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ExitPipToAppViaExpandButtonTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ExitPipToAppViaIntentTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ExitPipToAppViaIntentTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ExpandPipOnDoubleClickTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ExpandPipOnDoubleClickTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ExpandPipOnPinchOpenTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ExpandPipOnPinchOpenTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-FromSplitScreenAutoEnterPipOnGoToHomeTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.FromSplitScreenAutoEnterPipOnGoToHomeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-FromSplitScreenEnterPipOnUserLeaveHintTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.FromSplitScreenEnterPipOnUserLeaveHintTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-MovePipDownOnShelfHeightChange", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.MovePipDownOnShelfHeightChange"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-MovePipOnImeVisibilityChangeTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.MovePipOnImeVisibilityChangeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-MovePipUpOnShelfHeightChangeTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.MovePipUpOnShelfHeightChangeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-PipAspectRatioChangeTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.PipAspectRatioChangeTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-PipDragTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.PipDragTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-PipDragThenSnapTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.PipDragThenSnapTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-PipPinchInTest", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.PipPinchInTest"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-SetRequestedOrientationWhilePinned", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.SetRequestedOrientationWhilePinned"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-ShowPipAndRotateDisplay", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.ShowPipAndRotateDisplay"], + test_suites: ["device-tests"], +} + +// End breakdowns for WMShellFlickerTestsPip module +//////////////////////////////////////////////////////////////////////////////// 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 56fad952dc31..90e3f7fdb973 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 @@ -16,8 +16,19 @@ package com.android.wm.shell.back; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.view.WindowManager.TRANSIT_CLOSE; +import static android.view.WindowManager.TRANSIT_CLOSE_PREPARE_BACK_NAVIGATION; +import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION; import static android.window.BackNavigationInfo.KEY_NAVIGATION_FINISHED; +import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; +import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -25,6 +36,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; @@ -32,6 +44,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.app.ActivityManager; import android.app.IActivityTaskManager; import android.app.WindowConfiguration; import android.content.pm.ApplicationInfo; @@ -40,6 +53,7 @@ import android.graphics.Rect; import android.hardware.input.InputManager; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; import android.provider.Settings; @@ -51,11 +65,16 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; +import android.view.WindowManager; import android.window.BackEvent; import android.window.BackMotionEvent; import android.window.BackNavigationInfo; import android.window.IBackAnimationFinishedCallback; import android.window.IOnBackInvokedCallback; +import android.window.IWindowContainerToken; +import android.window.TransitionInfo; +import android.window.TransitionRequestInfo; +import android.window.WindowContainerToken; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; @@ -64,10 +83,10 @@ import com.android.internal.util.test.FakeSettingsProvider; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; +import com.android.wm.shell.shared.ShellSharedConstants; 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.ShellSharedConstants; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -128,6 +147,8 @@ public class BackAnimationControllerTest extends ShellTestCase { private ShellBackAnimationRegistry mShellBackAnimationRegistry; private Rect mTouchableRegion; + private BackAnimationController.BackTransitionHandler mBackTransitionHandler; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -165,6 +186,8 @@ public class BackAnimationControllerTest extends ShellTestCase { mShellExecutor.flushAll(); mTouchableRegion = new Rect(0, 0, 100, 100); mController.mTouchableArea.set(mTouchableRegion); + mBackTransitionHandler = mController.mBackTransitionHandler; + spyOn(mBackTransitionHandler); } private void createNavigationInfo(int backType, @@ -606,6 +629,198 @@ public class BackAnimationControllerTest extends ShellTestCase { mCrossTaskBackAnimation.getRunner()); } + @Test + public void testCloseAsExpectTransition() { + final int openTaskId = 1; + final int closeTaskId = 2; + mController.mApps = createAppAnimationTargets(openTaskId, closeTaskId); + final IBinder mockBinder = mock(IBinder.class); + final SurfaceControl.Transaction st = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction ft = mock(SurfaceControl.Transaction.class); + // Single close + final TransitionInfo.Change open = createAppChange(openTaskId, TRANSIT_OPEN, + FLAG_BACK_GESTURE_ANIMATED | FLAG_MOVED_TO_TOP); + final TransitionInfo.Change close = createAppChange(closeTaskId, TRANSIT_CLOSE, + FLAG_BACK_GESTURE_ANIMATED); + + TransitionInfo tInfo = createTransitionInfo(TRANSIT_CLOSE, open, close); + mBackTransitionHandler.mCloseTransitionRequested = true; + Transitions.TransitionFinishCallback callback = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.startAnimation(mockBinder, tInfo, st, ft, callback); + verify(mBackTransitionHandler).handleCloseTransition( + eq(tInfo), eq(st), eq(ft), eq(callback)); + mBackTransitionHandler.onAnimationFinished(); + verify(callback).onTransitionFinished(any()); + mBackTransitionHandler.mCloseTransitionRequested = false; + + // PREPARE + CLOSE + tInfo = createTransitionInfo(TRANSIT_PREPARE_BACK_NAVIGATION, open); + callback = mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.startAnimation(mockBinder, tInfo, st, ft, callback); + verify(mBackTransitionHandler).handlePrepareTransition( + eq(tInfo), eq(st), eq(ft), eq(callback)); + mBackTransitionHandler.mCloseTransitionRequested = true; + TransitionInfo tInfo2 = createTransitionInfo(TRANSIT_CLOSE, close); + Transitions.TransitionFinishCallback mergeCallback = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.mergeAnimation( + mock(IBinder.class), tInfo2, st, mock(IBinder.class), mergeCallback); + mBackTransitionHandler.onAnimationFinished(); + verify(callback).onTransitionFinished(any()); + verify(mergeCallback).onTransitionFinished(any()); + mBackTransitionHandler.mCloseTransitionRequested = false; + + // PREPARE contains close info + tInfo = createTransitionInfo(TRANSIT_PREPARE_BACK_NAVIGATION, open, close); + callback = mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.mCloseTransitionRequested = true; + mBackTransitionHandler.startAnimation(mockBinder, tInfo, st, ft, callback); + verify(mBackTransitionHandler).handleCloseTransition( + eq(tInfo), eq(st), eq(ft), eq(callback)); + mBackTransitionHandler.onAnimationFinished(); + verify(callback).onTransitionFinished(any()); + mBackTransitionHandler.mCloseTransitionRequested = false; + + // PREPARE then Cancel + tInfo = createTransitionInfo(TRANSIT_PREPARE_BACK_NAVIGATION, open); + callback = mock(Transitions.TransitionFinishCallback.class); + final TransitionRequestInfo requestInfo = new TransitionRequestInfo( + TRANSIT_PREPARE_BACK_NAVIGATION, null /* triggerTask */, + null /* remoteTransition */); + mBackTransitionHandler.handleRequest(mockBinder, requestInfo); + mBackTransitionHandler.startAnimation(mockBinder, tInfo, st, ft, callback); + verify(mBackTransitionHandler).handlePrepareTransition( + eq(tInfo), eq(st), eq(ft), eq(callback)); + final TransitionInfo.Change openToClose = createAppChange(openTaskId, TRANSIT_CLOSE, + FLAG_BACK_GESTURE_ANIMATED); + tInfo2 = createTransitionInfo(TRANSIT_CLOSE_PREPARE_BACK_NAVIGATION, openToClose); + mBackTransitionHandler.mClosePrepareTransition = mock(IBinder.class); + mergeCallback = mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.mergeAnimation(mBackTransitionHandler.mClosePrepareTransition, + tInfo2, st, mock(IBinder.class), mergeCallback); + assertTrue("Change should be consumed", tInfo2.getChanges().isEmpty()); + mBackTransitionHandler.onAnimationFinished(); + verify(callback).onTransitionFinished(any()); + } + + @Test + public void testCancelUnexpectedTransition() { + final int openTaskId = 1; + final int closeTaskId = 2; + mController.mApps = createAppAnimationTargets(openTaskId, closeTaskId); + final IBinder mockBinder = mock(IBinder.class); + final SurfaceControl.Transaction st = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction ft = mock(SurfaceControl.Transaction.class); + final TransitionInfo.Change open = createAppChange(openTaskId, TRANSIT_OPEN, + FLAG_BACK_GESTURE_ANIMATED | FLAG_MOVED_TO_TOP); + final TransitionInfo.Change close = createAppChange(closeTaskId, TRANSIT_CLOSE, + FLAG_BACK_GESTURE_ANIMATED); + + // Didn't trigger close transition + mBackTransitionHandler.mCloseTransitionRequested = false; + TransitionInfo prepareInfo = createTransitionInfo(TRANSIT_PREPARE_BACK_NAVIGATION, + open, close); + final Transitions.TransitionFinishCallback callback = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.handleRequest(mockBinder, mock(TransitionRequestInfo.class)); + boolean canHandle = mBackTransitionHandler.startAnimation( + mockBinder, prepareInfo, st, ft, callback); + assertFalse("Should not handle transition", canHandle); + assertNull(mBackTransitionHandler.mOnAnimationFinishCallback); + + // Didn't trigger close transition, but receive close target. + final TransitionRequestInfo requestInfo = new TransitionRequestInfo( + TRANSIT_PREPARE_BACK_NAVIGATION, null /* triggerTask */, + null /* remoteTransition */); + prepareInfo = createTransitionInfo(TRANSIT_PREPARE_BACK_NAVIGATION, open); + final Transitions.TransitionFinishCallback callback2 = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.handleRequest(mockBinder, requestInfo); + canHandle = mBackTransitionHandler.startAnimation(mockBinder, + prepareInfo, st, ft, callback2); + assertTrue("Handle prepare transition" , canHandle); + verify(mBackTransitionHandler).handlePrepareTransition( + eq(prepareInfo), eq(st), eq(ft), eq(callback2)); + final TransitionInfo closeInfo = createTransitionInfo(TRANSIT_CLOSE, close); + Transitions.TransitionFinishCallback mergeCallback = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.mergeAnimation(mock(IBinder.class), closeInfo, ft, + mock(IBinder.class), mergeCallback); + verify(callback2).onTransitionFinished(any()); + verify(mergeCallback, never()).onTransitionFinished(any()); + + // Didn't trigger close transition, but contains open target. + final int openTaskId2 = 3; + final Transitions.TransitionFinishCallback callback3 = + mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.handleRequest(mockBinder, requestInfo); + canHandle = mBackTransitionHandler.startAnimation( + mockBinder, prepareInfo, st, ft, callback3); + assertTrue("Handle prepare transition" , canHandle); + verify(mBackTransitionHandler).handlePrepareTransition( + eq(prepareInfo), eq(st), eq(ft), eq(callback3)); + final TransitionInfo.Change open2 = createAppChange( + openTaskId2, TRANSIT_OPEN, FLAG_MOVED_TO_TOP); + final TransitionInfo openInfo = createTransitionInfo(TRANSIT_OPEN, open2, close); + mergeCallback = mock(Transitions.TransitionFinishCallback.class); + mBackTransitionHandler.mergeAnimation(mock(IBinder.class), openInfo, ft, + mock(IBinder.class), mergeCallback); + verify(callback3).onTransitionFinished(any()); + verify(mergeCallback, never()).onTransitionFinished(any()); + } + + private RemoteAnimationTarget[] createAppAnimationTargets(int openTaskId, int closeTaskId) { + final RemoteAnimationTarget openT = createSingleAnimationTarget(openTaskId, + RemoteAnimationTarget.MODE_OPENING); + final RemoteAnimationTarget closeT = createSingleAnimationTarget(closeTaskId, + RemoteAnimationTarget.MODE_CLOSING); + return new RemoteAnimationTarget[]{openT, closeT}; + } + + private RemoteAnimationTarget createSingleAnimationTarget(int taskId, int mode) { + final Rect fakeR = new Rect(); + final Point fakeP = new Point(); + final ActivityManager.RunningTaskInfo openTaskInfo = new ActivityManager.RunningTaskInfo(); + openTaskInfo.taskId = taskId; + openTaskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); + return new RemoteAnimationTarget( + taskId, mode, mock(SurfaceControl.class), false, fakeR, fakeR, + 0, fakeP, fakeR, fakeR, new WindowConfiguration(), false, + mock(SurfaceControl.class), fakeR, openTaskInfo, false); + } + private TransitionInfo.Change createAppChange( + int taskId, @TransitionInfo.TransitionMode int mode, + @TransitionInfo.ChangeFlags int flags) { + final TransitionInfo.Change change; + SurfaceControl.Builder b = new SurfaceControl.Builder() + .setName("test task"); + if (taskId != INVALID_TASK_ID) { + final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); + taskInfo.taskId = taskId; + taskInfo.token = new WindowContainerToken(mock(IWindowContainerToken.class)); + change = new TransitionInfo.Change( + taskInfo.token, b.build()); + change.setTaskInfo(taskInfo); + } else { + change = new TransitionInfo.Change( + null, b.build()); + + } + change.setMode(mode); + change.setFlags(flags); + return change; + } + + private static TransitionInfo createTransitionInfo( + @WindowManager.TransitionType int type, TransitionInfo.Change ... changes) { + final TransitionInfo info = new TransitionInfo(type, 0); + for (int i = 0; i < changes.length; ++i) { + info.addChange(changes[i]); + } + return info; + } + private void verifySystemBackBehavior(int type, BackAnimationRunner animation) throws RemoteException { final BackAnimationRunner animationRunner = spy(animation); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt index e35995775f76..9ec62c965a14 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt @@ -124,6 +124,7 @@ class BubbleDataRepositoryTest : ShellTestCase() { private val testHandler = Handler(Looper.getMainLooper()) private val mainExecutor = HandlerExecutor(testHandler) + private val bgExecutor = HandlerExecutor(testHandler) private val launcherApps = mock<LauncherApps>() private val persistedBubbles = SparseArray<List<BubbleEntity>>() @@ -134,7 +135,8 @@ class BubbleDataRepositoryTest : ShellTestCase() { @Before fun setup() { persistentRepository = BubblePersistentRepository(mContext) - dataRepository = spy(BubbleDataRepository(launcherApps, mainExecutor, persistentRepository)) + dataRepository = + spy(BubbleDataRepository(launcherApps, mainExecutor, bgExecutor, persistentRepository)) persistedBubbles.put(0, user0BubbleEntities) persistedBubbles.put(1, user1BubbleEntities) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java index c138a2498d35..859602ec709f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java @@ -117,6 +117,8 @@ public class BubbleDataTest extends ShellTestCase { private BubbleEducationController mEducationController; @Mock private ShellExecutor mMainExecutor; + @Mock + private ShellExecutor mBgExecutor; @Captor private ArgumentCaptor<BubbleData.Update> mUpdateCaptor; @@ -144,47 +146,47 @@ public class BubbleDataTest extends ShellTestCase { when(ranking.isTextChanged()).thenReturn(true); mEntryInterruptive = createBubbleEntry(1, "interruptive", "package.d", ranking); mBubbleInterruptive = new Bubble(mEntryInterruptive, mBubbleMetadataFlagListener, null, - mMainExecutor); + mMainExecutor, mBgExecutor); mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d", null); mBubbleDismissed = new Bubble(mEntryDismissed, mBubbleMetadataFlagListener, null, - mMainExecutor); + mMainExecutor, mBgExecutor); mEntryLocusId = createBubbleEntry(1, "keyLocus", "package.e", null, new LocusId("locusId1")); mBubbleLocusId = new Bubble(mEntryLocusId, mBubbleMetadataFlagListener, null /* pendingIntentCanceledListener */, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleA1 = new Bubble(mEntryA1, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleA2 = new Bubble(mEntryA2, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleA3 = new Bubble(mEntryA3, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleB1 = new Bubble(mEntryB1, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleB2 = new Bubble(mEntryB2, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleB3 = new Bubble(mEntryB3, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); mBubbleC1 = new Bubble(mEntryC1, mBubbleMetadataFlagListener, mPendingIntentCanceledListener, - mMainExecutor); + mMainExecutor, mBgExecutor); Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class); appBubbleIntent.setPackage(mContext.getPackageName()); @@ -192,12 +194,12 @@ public class BubbleDataTest extends ShellTestCase { appBubbleIntent, new UserHandle(1), mock(Icon.class), - mMainExecutor); + mMainExecutor, mBgExecutor); mPositioner = new TestableBubblePositioner(mContext, mContext.getSystemService(WindowManager.class)); mBubbleData = new BubbleData(getContext(), mBubbleLogger, mPositioner, mEducationController, - mMainExecutor); + mMainExecutor, mBgExecutor); // Used by BubbleData to set lastAccessedTime when(mTimeSource.currentTimeMillis()).thenReturn(1000L); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java index afec1ee12341..50c4a1828026 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java @@ -61,6 +61,8 @@ public class BubbleTest extends ShellTestCase { private StatusBarNotification mSbn; @Mock private ShellExecutor mMainExecutor; + @Mock + private ShellExecutor mBgExecutor; private BubbleEntry mBubbleEntry; private Bundle mExtras; @@ -85,7 +87,8 @@ public class BubbleTest extends ShellTestCase { when(mNotif.getBubbleMetadata()).thenReturn(metadata); when(mSbn.getKey()).thenReturn("mock"); mBubbleEntry = new BubbleEntry(mSbn, null, true, false, false, false); - mBubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor); + mBubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor, + mBgExecutor); } @Test @@ -176,7 +179,8 @@ public class BubbleTest extends ShellTestCase { @Test public void testBubbleIsConversation_hasNoShortcut() { - Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor); + Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor, + mBgExecutor); assertThat(bubble.getShortcutInfo()).isNull(); assertThat(bubble.isConversation()).isFalse(); } @@ -199,7 +203,7 @@ public class BubbleTest extends ShellTestCase { Intent intent = new Intent(mContext, BubblesTestActivity.class); intent.setPackage(mContext.getPackageName()); Bubble bubble = Bubble.createAppBubble(intent, new UserHandle(1 /* userId */), - null /* icon */, mMainExecutor); + null /* icon */, mMainExecutor, mBgExecutor); BubbleInfo bubbleInfo = bubble.asBubbleBarBubble(); assertThat(bubble.getShortcutInfo()).isNull(); @@ -215,6 +219,6 @@ public class BubbleTest extends ShellTestCase { .build(); return new Bubble("mockKey", shortcutInfo, 10, Resources.ID_NULL, "mockTitle", 0 /* taskId */, "mockLocus", true /* isDismissible */, - mMainExecutor, mBubbleMetadataFlagListener); + mMainExecutor, mBgExecutor, mBubbleMetadataFlagListener); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt index 4a4c5e860bb2..8035e917d5b4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt @@ -70,6 +70,7 @@ class BubbleViewInfoTest : ShellTestCase() { private lateinit var bubble: Bubble private lateinit var bubbleController: BubbleController private lateinit var mainExecutor: ShellExecutor + private lateinit var bgExecutor: ShellExecutor private lateinit var bubbleStackView: BubbleStackView private lateinit var bubbleBarLayerView: BubbleBarLayerView private lateinit var bubblePositioner: BubblePositioner @@ -92,6 +93,7 @@ class BubbleViewInfoTest : ShellTestCase() { ) mainExecutor = TestShellExecutor() + bgExecutor = TestShellExecutor() val windowManager = context.getSystemService(WindowManager::class.java) val shellInit = ShellInit(mainExecutor) val shellCommandHandler = ShellCommandHandler() @@ -104,7 +106,8 @@ class BubbleViewInfoTest : ShellTestCase() { mock<BubbleLogger>(), bubblePositioner, BubbleEducationController(context), - mainExecutor + mainExecutor, + bgExecutor ) val surfaceSynchronizer = { obj: Runnable -> obj.run() } @@ -132,7 +135,7 @@ class BubbleViewInfoTest : ShellTestCase() { null, mainExecutor, mock<Handler>(), - mock<ShellExecutor>(), + bgExecutor, mock<TaskViewTransitions>(), mock<Transitions>(), mock<SyncTransactionQueue>(), @@ -256,7 +259,7 @@ class BubbleViewInfoTest : ShellTestCase() { "mockLocus", true /* isDismissible */, mainExecutor, - metadataFlagListener - ) + bgExecutor, + metadataFlagListener) } } 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 654d7a8ecf91..f8f0db930e6c 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 @@ -43,6 +43,7 @@ import android.view.inputmethod.ImeTracker; import androidx.test.filters.SmallTest; import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import org.junit.Before; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index cfe8e07aa6e5..09fcd8b02010 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -19,9 +19,9 @@ package com.android.wm.shell.common.split; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS; import static com.google.common.truth.Truth.assertThat; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIComponentTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIComponentTest.kt new file mode 100644 index 000000000000..2c203c466c6e --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIComponentTest.kt @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.impl + +import android.app.ActivityManager +import android.graphics.Point +import android.testing.AndroidTestingRunner +import android.view.View +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.common.DisplayLayout +import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.compatui.api.CompatUIComponent +import com.android.wm.shell.compatui.api.CompatUIComponentState +import com.android.wm.shell.compatui.api.CompatUIInfo +import com.android.wm.shell.compatui.api.CompatUIState +import junit.framework.Assert.assertEquals +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.mock + +/** + * Tests for {@link CompatUIComponent}. + * + * Build/Install/Run: + * atest WMShellUnitTests:CompatUIComponentTest + */ +@RunWith(AndroidTestingRunner::class) +@SmallTest +class CompatUIComponentTest : ShellTestCase() { + + private lateinit var component: CompatUIComponent + private lateinit var layout: FakeCompatUILayout + private lateinit var spec: FakeCompatUISpec + private lateinit var state: CompatUIState + private lateinit var info: CompatUIInfo + private lateinit var syncQueue: SyncTransactionQueue + private lateinit var displayLayout: DisplayLayout + private lateinit var view: View + private lateinit var position: Point + private lateinit var componentState: CompatUIComponentState + + @JvmField + @Rule + val compatUIHandlerRule: CompatUIHandlerRule = CompatUIHandlerRule() + + @Before + fun setUp() { + state = CompatUIState() + view = View(mContext) + position = Point(123, 456) + layout = FakeCompatUILayout(viewBuilderReturn = view, positionBuilderReturn = position) + spec = FakeCompatUISpec("comp", layout = layout) + info = testCompatUIInfo() + syncQueue = mock<SyncTransactionQueue>() + displayLayout = mock<DisplayLayout>() + component = + CompatUIComponent(spec.getSpec(), + "compId", + mContext, + state, + info, + syncQueue, + displayLayout) + componentState = object : CompatUIComponentState {} + state.registerUIComponent("compId", component, componentState) + } + + @Test + fun `when initLayout is invoked spec fields are used`() { + compatUIHandlerRule.postBlocking { + component.initLayout(info) + } + with(layout) { + assertViewBuilderInvocation(1) + assertEquals(info, lastViewBuilderCompatUIInfo) + assertEquals(componentState, lastViewBuilderCompState) + assertViewBinderInvocation(0) + assertPositionFactoryInvocation(1) + assertEquals(info, lastPositionFactoryCompatUIInfo) + assertEquals(view, lastPositionFactoryView) + assertEquals(componentState, lastPositionFactoryCompState) + assertEquals(state.sharedState, lastPositionFactorySharedState) + } + } + + @Test + fun `when update is invoked only position and binder spec fields are used`() { + compatUIHandlerRule.postBlocking { + component.initLayout(info) + layout.resetState() + component.update(info) + } + with(layout) { + assertViewBuilderInvocation(0) + assertViewBinderInvocation(1) + assertPositionFactoryInvocation(1) + } + } + + private fun testCompatUIInfo(): CompatUIInfo { + val taskInfo = ActivityManager.RunningTaskInfo() + taskInfo.taskId = 1 + return CompatUIInfo(taskInfo, null) + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIHandlerRule.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIHandlerRule.kt new file mode 100644 index 000000000000..4b8b65c784e9 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIHandlerRule.kt @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.impl + +import android.os.HandlerThread +import java.util.concurrent.CountDownLatch +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +/** + * Utility {@link TestRule} to manage Handlers in Compat UI tests. + */ +class CompatUIHandlerRule : TestRule { + + private lateinit var handler: HandlerThread + + /** + * Makes the HandlerThread available during the test + */ + override fun apply(base: Statement?, description: Description?): Statement { + handler = HandlerThread("CompatUIHandler").apply { + start() + } + return object : Statement() { + @Throws(Throwable::class) + override fun evaluate() { + try { + base!!.evaluate() + } finally { + handler.quitSafely() + } + } + } + } + + /** + * Posts a {@link Runnable} for the Handler + * @param runnable The Runnable to execute + */ + fun postBlocking(runnable: Runnable) { + val countDown = CountDownLatch(/* count = */ 1) + handler.threadHandler.post{ + runnable.run() + countDown.countDown() + } + try { + countDown.await() + } catch (e: InterruptedException) { + // No-op + } + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt index 43bd41275daa..4f0e5b9cbfbf 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/CompatUIStateUtil.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.compatui.impl import com.android.wm.shell.compatui.api.CompatUIComponentState -import com.android.wm.shell.compatui.api.CompatUISpec import com.android.wm.shell.compatui.api.CompatUIState import junit.framework.Assert.assertEquals import junit.framework.Assert.assertNotNull diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt index 8136074b7aa6..66852ad5ab5d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIHandlerTest.kt @@ -18,13 +18,21 @@ package com.android.wm.shell.compatui.impl import android.app.ActivityManager import android.testing.AndroidTestingRunner +import android.view.View import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.TestShellExecutor +import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.ShellExecutor +import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.api.CompatUIComponentState import com.android.wm.shell.compatui.api.CompatUIInfo import com.android.wm.shell.compatui.api.CompatUIState import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.mock /** * Tests for {@link DefaultCompatUIHandler}. @@ -34,20 +42,37 @@ import org.junit.runner.RunWith */ @RunWith(AndroidTestingRunner::class) @SmallTest -class DefaultCompatUIHandlerTest { +class DefaultCompatUIHandlerTest : ShellTestCase() { + + @JvmField + @Rule + val compatUIHandlerRule: CompatUIHandlerRule = CompatUIHandlerRule() lateinit var compatUIRepository: FakeCompatUIRepository lateinit var compatUIHandler: DefaultCompatUIHandler lateinit var compatUIState: CompatUIState lateinit var fakeIdGenerator: FakeCompatUIComponentIdGenerator + lateinit var syncQueue: SyncTransactionQueue + lateinit var displayController: DisplayController + lateinit var shellExecutor: TestShellExecutor + lateinit var componentFactory: FakeCompatUIComponentFactory @Before fun setUp() { + shellExecutor = TestShellExecutor() compatUIRepository = FakeCompatUIRepository() compatUIState = CompatUIState() fakeIdGenerator = FakeCompatUIComponentIdGenerator("compId") - compatUIHandler = DefaultCompatUIHandler(compatUIRepository, compatUIState, - fakeIdGenerator) + syncQueue = mock<SyncTransactionQueue>() + displayController = mock<DisplayController>() + componentFactory = FakeCompatUIComponentFactory(mContext, syncQueue, displayController) + compatUIHandler = + DefaultCompatUIHandler( + compatUIRepository, + compatUIState, + fakeIdGenerator, + componentFactory, + shellExecutor) } @Test @@ -57,12 +82,18 @@ class DefaultCompatUIHandlerTest { creationReturn = false, removalReturn = false ) - val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec() + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = + FakeCompatUISpec(name = "one", + lifecycle = fakeLifecycle, + layout = fakeCompatUILayout).getSpec() compatUIRepository.addSpec(fakeCompatUISpec) val generatedId = fakeIdGenerator.generatedComponentId - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeIdGenerator.assertGenerateInvocations(1) fakeLifecycle.assertCreationInvocation(1) @@ -71,7 +102,9 @@ class DefaultCompatUIHandlerTest { compatUIState.assertHasNoStateFor(generatedId) compatUIState.assertHasNoComponentFor(generatedId) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(2) fakeLifecycle.assertRemovalInvocation(0) fakeLifecycle.assertInitialStateInvocation(0) @@ -86,12 +119,18 @@ class DefaultCompatUIHandlerTest { creationReturn = true, removalReturn = false ) - val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec() + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = + FakeCompatUISpec(name = "one", + lifecycle = fakeLifecycle, + layout = fakeCompatUILayout).getSpec() compatUIRepository.addSpec(fakeCompatUISpec) val generatedId = fakeIdGenerator.generatedComponentId - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(0) @@ -99,7 +138,9 @@ class DefaultCompatUIHandlerTest { compatUIState.assertHasNoStateFor(generatedId) compatUIState.assertHasComponentFor(generatedId) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(1) @@ -117,12 +158,18 @@ class DefaultCompatUIHandlerTest { removalReturn = false, initialState = { _, _ -> fakeComponentState } ) - val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec() + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = + FakeCompatUISpec(name = "one", + lifecycle = fakeLifecycle, + layout = fakeCompatUILayout).getSpec() compatUIRepository.addSpec(fakeCompatUISpec) val generatedId = fakeIdGenerator.generatedComponentId - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(0) @@ -130,7 +177,9 @@ class DefaultCompatUIHandlerTest { compatUIState.assertHasStateEqualsTo(generatedId, fakeComponentState) compatUIState.assertHasComponentFor(generatedId) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(1) @@ -148,12 +197,18 @@ class DefaultCompatUIHandlerTest { removalReturn = true, initialState = { _, _ -> fakeComponentState } ) - val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec() + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = + FakeCompatUISpec(name = "one", + lifecycle = fakeLifecycle, + layout = fakeCompatUILayout).getSpec() compatUIRepository.addSpec(fakeCompatUISpec) val generatedId = fakeIdGenerator.generatedComponentId - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(0) @@ -161,7 +216,9 @@ class DefaultCompatUIHandlerTest { compatUIState.assertHasStateEqualsTo(generatedId, fakeComponentState) compatUIState.assertHasComponentFor(generatedId) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeLifecycle.assertCreationInvocation(1) fakeLifecycle.assertRemovalInvocation(1) @@ -177,17 +234,56 @@ class DefaultCompatUIHandlerTest { creationReturn = true, removalReturn = true, ) - val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle).getSpec() + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle, + fakeCompatUILayout).getSpec() compatUIRepository.addSpec(fakeCompatUISpec) // Component creation fakeIdGenerator.assertGenerateInvocations(0) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeIdGenerator.assertGenerateInvocations(1) - compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } fakeIdGenerator.assertGenerateInvocations(2) } + @Test + fun `viewBuilder and viewBinder invoked if component is created and released when destroyed`() { + // We add a spec to the repository + val fakeLifecycle = FakeCompatUILifecyclePredicates( + creationReturn = true, + removalReturn = true, + ) + val fakeCompatUILayout = FakeCompatUILayout(viewBuilderReturn = View(mContext)) + val fakeCompatUISpec = FakeCompatUISpec("one", fakeLifecycle, + fakeCompatUILayout).getSpec() + compatUIRepository.addSpec(fakeCompatUISpec) + + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } + shellExecutor.flushAll() + componentFactory.assertInvocations(1) + fakeCompatUILayout.assertViewBuilderInvocation(1) + fakeCompatUILayout.assertViewBinderInvocation(1) + fakeCompatUILayout.assertViewReleaserInvocation(0) + + compatUIHandlerRule.postBlocking { + compatUIHandler.onCompatInfoChanged(testCompatUIInfo()) + } + shellExecutor.flushAll() + + componentFactory.assertInvocations(1) + fakeCompatUILayout.assertViewBuilderInvocation(1) + fakeCompatUILayout.assertViewBinderInvocation(1) + fakeCompatUILayout.assertViewReleaserInvocation(1) + } + + private fun testCompatUIInfo(): CompatUIInfo { val taskInfo = ActivityManager.RunningTaskInfo() taskInfo.taskId = 1 diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt index e35acb2ca0e9..319122d1e051 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/DefaultCompatUIRepositoryTest.kt @@ -16,9 +16,13 @@ package com.android.wm.shell.compatui.impl + +import android.graphics.Point import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.testing.AndroidTestingRunner +import android.view.View import androidx.test.filters.SmallTest +import com.android.wm.shell.compatui.api.CompatUILayout import com.android.wm.shell.compatui.api.CompatUILifecyclePredicates import com.android.wm.shell.compatui.api.CompatUIRepository import com.android.wm.shell.compatui.api.CompatUISpec @@ -89,8 +93,14 @@ class DefaultCompatUIRepositoryTest { } private fun specById(name: String): CompatUISpec = - CompatUISpec(name = name, lifecycle = CompatUILifecyclePredicates( - creationPredicate = { _, _ -> true }, - removalPredicate = { _, _, _ -> true } - )) + CompatUISpec(name = name, + lifecycle = CompatUILifecyclePredicates( + creationPredicate = { _, _ -> true }, + removalPredicate = { _, _, _ -> true } + ), + layout = CompatUILayout( + viewBuilder = { ctx, _, _ -> View(ctx) }, + positionFactory = { _, _, _, _ -> Point(0, 0) } + ) + ) }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentFactory.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentFactory.kt new file mode 100644 index 000000000000..782add84a36c --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUIComponentFactory.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.impl + +import android.content.Context +import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.common.SyncTransactionQueue +import com.android.wm.shell.compatui.api.CompatUIComponent +import com.android.wm.shell.compatui.api.CompatUIComponentFactory +import com.android.wm.shell.compatui.api.CompatUIInfo +import com.android.wm.shell.compatui.api.CompatUISpec +import com.android.wm.shell.compatui.api.CompatUIState +import junit.framework.Assert.assertEquals + +/** + * Fake {@link CompatUIComponentFactory} implementation. + */ +class FakeCompatUIComponentFactory( + private val context: Context, + private val syncQueue: SyncTransactionQueue, + private val displayController: DisplayController +) : CompatUIComponentFactory { + + var lastSpec: CompatUISpec? = null + var lastCompId: String? = null + var lastState: CompatUIState? = null + var lastInfo: CompatUIInfo? = null + + var numberInvocations = 0 + + override fun create( + spec: CompatUISpec, + compId: String, + state: CompatUIState, + compatUIInfo: CompatUIInfo + ): CompatUIComponent { + lastSpec = spec + lastCompId = compId + lastState = state + lastInfo = compatUIInfo + numberInvocations++ + return CompatUIComponent( + spec, + compId, + context, + state, + compatUIInfo, + syncQueue, + displayController.getDisplayLayout(compatUIInfo.taskInfo.displayId) + ) + } + + fun assertInvocations(expected: Int) = + assertEquals(expected, numberInvocations) +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILayout.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILayout.kt new file mode 100644 index 000000000000..d7a178ab69e8 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILayout.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.impl + +import android.content.Context +import android.graphics.Point +import android.view.View +import com.android.wm.shell.compatui.api.CompatUIComponentState +import com.android.wm.shell.compatui.api.CompatUIInfo +import com.android.wm.shell.compatui.api.CompatUILayout +import com.android.wm.shell.compatui.api.CompatUISharedState +import junit.framework.Assert.assertEquals + +/** + * Fake class for {@link CompatUILayout} + */ +class FakeCompatUILayout( + private val zOrderReturn: Int = 0, + private val layoutParamFlagsReturn: Int = 0, + private val viewBuilderReturn: View, + private val positionBuilderReturn: Point = Point(0, 0) +) { + + var viewBuilderInvocation = 0 + var viewBinderInvocation = 0 + var positionFactoryInvocation = 0 + var viewReleaserInvocation = 0 + + var lastViewBuilderContext: Context? = null + var lastViewBuilderCompatUIInfo: CompatUIInfo? = null + var lastViewBuilderCompState: CompatUIComponentState? = null + var lastViewBinderView: View? = null + var lastViewBinderCompatUIInfo: CompatUIInfo? = null + var lastViewBinderSharedState: CompatUISharedState? = null + var lastViewBinderCompState: CompatUIComponentState? = null + var lastPositionFactoryView: View? = null + var lastPositionFactoryCompatUIInfo: CompatUIInfo? = null + var lastPositionFactorySharedState: CompatUISharedState? = null + var lastPositionFactoryCompState: CompatUIComponentState? = null + + fun getLayout() = CompatUILayout( + zOrder = zOrderReturn, + layoutParamFlags = layoutParamFlagsReturn, + viewBuilder = { ctx, info, componentState -> + lastViewBuilderContext = ctx + lastViewBuilderCompatUIInfo = info + lastViewBuilderCompState = componentState + viewBuilderInvocation++ + viewBuilderReturn + }, + viewBinder = { view, info, sharedState, componentState -> + lastViewBinderView = view + lastViewBinderCompatUIInfo = info + lastViewBinderCompState = componentState + lastViewBinderSharedState = sharedState + viewBinderInvocation++ + }, + positionFactory = { view, info, sharedState, componentState -> + lastPositionFactoryView = view + lastPositionFactoryCompatUIInfo = info + lastPositionFactoryCompState = componentState + lastPositionFactorySharedState = sharedState + positionFactoryInvocation++ + positionBuilderReturn + }, + viewReleaser = { viewReleaserInvocation++ } + ) + + fun assertViewBuilderInvocation(expected: Int) = + assertEquals(expected, viewBuilderInvocation) + + fun assertViewBinderInvocation(expected: Int) = + assertEquals(expected, viewBinderInvocation) + + fun assertViewReleaserInvocation(expected: Int) = + assertEquals(expected, viewReleaserInvocation) + + fun assertPositionFactoryInvocation(expected: Int) = + assertEquals(expected, positionFactoryInvocation) + + fun resetState() { + viewBuilderInvocation = 0 + viewBinderInvocation = 0 + positionFactoryInvocation = 0 + viewReleaserInvocation = 0 + lastViewBuilderCompatUIInfo = null + lastViewBuilderCompState = null + lastViewBinderView = null + lastViewBinderCompatUIInfo = null + lastViewBinderSharedState = null + lastViewBinderCompState = null + lastPositionFactoryView = null + lastPositionFactoryCompatUIInfo = null + lastPositionFactorySharedState = null + lastPositionFactoryCompState = null + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt index bbaa2db07aaa..f742ca32e63d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUILifecyclePredicates.kt @@ -26,8 +26,8 @@ import junit.framework.Assert.assertEquals * Fake class for {@link CompatUILifecycle} */ class FakeCompatUILifecyclePredicates( - private val creationReturn: Boolean, - private val removalReturn: Boolean, + private val creationReturn: Boolean = false, + private val removalReturn: Boolean = false, private val initialState: ( CompatUIInfo, CompatUISharedState diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt index 1ecd52e2b3ff..0912bf115666 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/impl/FakeCompatUISpec.kt @@ -23,10 +23,13 @@ import com.android.wm.shell.compatui.api.CompatUISpec */ class FakeCompatUISpec( val name: String, - val lifecycle: FakeCompatUILifecyclePredicates + val lifecycle: FakeCompatUILifecyclePredicates = FakeCompatUILifecyclePredicates(), + val layout: FakeCompatUILayout ) { fun getSpec(): CompatUISpec = CompatUISpec( name = name, - lifecycle = lifecycle.getLifecycle() + log = {str -> android.util.Log.d("COMPAT_UI_TEST", str)}, + lifecycle = lifecycle.getLifecycle(), + layout = layout.getLayout() ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt index 4548fcb06c55..70b366110692 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt @@ -16,14 +16,17 @@ package com.android.wm.shell.desktopmode -import com.android.dx.mockito.inline.extended.ExtendedMockito +import com.android.dx.mockito.inline.extended.ExtendedMockito.verify import com.android.internal.util.FrameworkStatsLog import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_MINIMIZE_REASON +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON import kotlinx.coroutines.runBlocking -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.kotlin.eq @@ -33,7 +36,7 @@ import org.mockito.kotlin.eq */ class DesktopModeEventLoggerTest { - private val desktopModeEventLogger = DesktopModeEventLogger() + private val desktopModeEventLogger = DesktopModeEventLogger() @JvmField @Rule @@ -44,7 +47,7 @@ class DesktopModeEventLoggerTest { fun logSessionEnter_enterReason() = runBlocking { desktopModeEventLogger.logSessionEnter(sessionId = SESSION_ID, EnterReason.UNKNOWN_ENTER) - ExtendedMockito.verify { + verify { FrameworkStatsLog.write( eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED), /* event */ @@ -63,7 +66,7 @@ class DesktopModeEventLoggerTest { fun logSessionExit_exitReason() = runBlocking { desktopModeEventLogger.logSessionExit(sessionId = SESSION_ID, ExitReason.UNKNOWN_EXIT) - ExtendedMockito.verify { + verify { FrameworkStatsLog.write( eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED), /* event */ @@ -82,7 +85,7 @@ class DesktopModeEventLoggerTest { fun logTaskAdded_taskUpdate() = runBlocking { desktopModeEventLogger.logTaskAdded(sessionId = SESSION_ID, TASK_UPDATE) - ExtendedMockito.verify { + verify { FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), /* task_event */ eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED), @@ -99,7 +102,9 @@ class DesktopModeEventLoggerTest { /* task_y */ eq(TASK_UPDATE.taskY), /* session_id */ - eq(SESSION_ID)) + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON)) } } @@ -107,7 +112,7 @@ class DesktopModeEventLoggerTest { fun logTaskRemoved_taskUpdate() = runBlocking { desktopModeEventLogger.logTaskRemoved(sessionId = SESSION_ID, TASK_UPDATE) - ExtendedMockito.verify { + verify { FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), /* task_event */ eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED), @@ -124,7 +129,9 @@ class DesktopModeEventLoggerTest { /* task_y */ eq(TASK_UPDATE.taskY), /* session_id */ - eq(SESSION_ID)) + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON)) } } @@ -132,10 +139,11 @@ class DesktopModeEventLoggerTest { fun logTaskInfoChanged_taskUpdate() = runBlocking { desktopModeEventLogger.logTaskInfoChanged(sessionId = SESSION_ID, TASK_UPDATE) - ExtendedMockito.verify { + verify { FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), /* task_event */ - eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), /* instance_id */ eq(TASK_UPDATE.instanceId), /* uid */ @@ -149,7 +157,71 @@ class DesktopModeEventLoggerTest { /* task_y */ eq(TASK_UPDATE.taskY), /* session_id */ - eq(SESSION_ID)) + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON)) + } + } + + @Test + fun logTaskInfoChanged_logsTaskUpdateWithMinimizeReason() = runBlocking { + desktopModeEventLogger.logTaskInfoChanged(sessionId = SESSION_ID, + createTaskUpdate(minimizeReason = MinimizeReason.TASK_LIMIT)) + + verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), + /* task_event */ + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + /* instance_id */ + eq(TASK_UPDATE.instanceId), + /* uid */ + eq(TASK_UPDATE.uid), + /* task_height */ + eq(TASK_UPDATE.taskHeight), + /* task_width */ + eq(TASK_UPDATE.taskWidth), + /* task_x */ + eq(TASK_UPDATE.taskX), + /* task_y */ + eq(TASK_UPDATE.taskY), + /* session_id */ + eq(SESSION_ID), + /* minimize_reason */ + eq(MinimizeReason.TASK_LIMIT.reason), + /* unminimize_reason */ + eq(UNSET_UNMINIMIZE_REASON)) + } + } + + @Test + fun logTaskInfoChanged_logsTaskUpdateWithUnminimizeReason() = runBlocking { + desktopModeEventLogger.logTaskInfoChanged(sessionId = SESSION_ID, + createTaskUpdate(unminimizeReason = UnminimizeReason.TASKBAR_TAP)) + + verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE), + /* task_event */ + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + /* instance_id */ + eq(TASK_UPDATE.instanceId), + /* uid */ + eq(TASK_UPDATE.uid), + /* task_height */ + eq(TASK_UPDATE.taskHeight), + /* task_width */ + eq(TASK_UPDATE.taskWidth), + /* task_x */ + eq(TASK_UPDATE.taskX), + /* task_y */ + eq(TASK_UPDATE.taskY), + /* session_id */ + eq(SESSION_ID), + /* minimize_reason */ + eq(UNSET_MINIMIZE_REASON), + /* unminimize_reason */ + eq(UnminimizeReason.TASKBAR_TAP.reason)) } } @@ -165,5 +237,11 @@ class DesktopModeEventLoggerTest { private val TASK_UPDATE = TaskUpdate( TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y ) + + private fun createTaskUpdate( + minimizeReason: MinimizeReason? = null, + unminimizeReason: UnminimizeReason? = null, + ) = TaskUpdate(TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y, minimizeReason, + unminimizeReason) } }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt index 2dea43b508ae..f558e87c4ed7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt @@ -17,9 +17,6 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo -import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM -import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN -import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.graphics.Rect import android.graphics.Region import android.testing.AndroidTestingRunner @@ -38,6 +35,11 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.kotlin.whenever +/** + * Test class for [DesktopModeVisualIndicator] + * + * Usage: atest WMShellUnitTests:DesktopModeVisualIndicatorTest + */ @SmallTest @RunWith(AndroidTestingRunner::class) class DesktopModeVisualIndicatorTest : ShellTestCase() { @@ -52,8 +54,6 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Before fun setUp() { - visualIndicator = DesktopModeVisualIndicator(syncQueue, taskInfo, displayController, - context, taskSurface, taskDisplayAreaOrganizer) whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width()) whenever(displayLayout.height()).thenReturn(DISPLAY_BOUNDS.height()) whenever(displayLayout.stableInsets()).thenReturn(STABLE_INSETS) @@ -61,41 +61,52 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Test fun testFullscreenRegionCalculation() { - var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, CAPTION_HEIGHT) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) + var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) - testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FREEFORM, CAPTION_HEIGHT) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_transition_region_thickness) val toFullscreenScale = mContext.resources.getFloat( R.dimen.desktop_mode_fullscreen_region_scale ) val toFullscreenWidth = displayLayout.width() * toFullscreenScale - assertThat(testRegion.bounds).isEqualTo(Rect( (DISPLAY_BOUNDS.width() / 2f - toFullscreenWidth / 2f).toInt(), -50, (DISPLAY_BOUNDS.width() / 2f + toFullscreenWidth / 2f).toInt(), transitionHeight)) - testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, CAPTION_HEIGHT) + + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) + + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, transitionHeight)) } @Test fun testSplitLeftRegionCalculation() { val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_split_from_desktop_height) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) var testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FREEFORM, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, transitionHeight, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) } @@ -103,27 +114,35 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { fun testSplitRightRegionCalculation() { val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_split_from_desktop_height) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) var testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FREEFORM, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, transitionHeight, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) + testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) } @Test fun testToDesktopRegionCalculation() { + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) val fullscreenRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, CAPTION_HEIGHT) + CAPTION_HEIGHT) val splitLeftRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) val splitRightRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) val desktopRegion = visualIndicator.calculateToDesktopRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, splitLeftRegion, splitRightRegion, fullscreenRegion) + splitLeftRegion, splitRightRegion, fullscreenRegion) var testRegion = Region() testRegion.union(DISPLAY_BOUNDS) testRegion.op(splitLeftRegion, Region.Op.DIFFERENCE) @@ -132,6 +151,11 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { assertThat(desktopRegion).isEqualTo(testRegion) } + private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) { + visualIndicator = DesktopModeVisualIndicator(syncQueue, taskInfo, displayController, + context, taskSurface, taskDisplayAreaOrganizer, dragStartState) + } + companion object { private const val TRANSITION_AREA_WIDTH = 32 private const val CAPTION_HEIGHT = 50 diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 7bb54498b877..a841e168af18 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -84,7 +84,6 @@ import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource.UNKNOWN -import com.android.wm.shell.common.split.SplitScreenConstants import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask @@ -95,6 +94,7 @@ import com.android.wm.shell.recents.RecentTasksController import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.desktopmode.DesktopModeStatus +import com.android.wm.shell.shared.split.SplitScreenConstants import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellCommandHandler import com.android.wm.shell.sysui.ShellController @@ -160,6 +160,7 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock lateinit var mReturnToDragStartAnimator: ReturnToDragStartAnimator @Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler @Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler + @Mock lateinit var dragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler @Mock lateinit var toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler @Mock lateinit var dragToDesktopTransitionHandler: DragToDesktopTransitionHandler @@ -254,6 +255,7 @@ class DesktopTasksControllerTest : ShellTestCase() { mReturnToDragStartAnimator, enterDesktopTransitionHandler, exitDesktopTransitionHandler, + dragAndDropTransitionHandler, toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, taskRepository, @@ -641,6 +643,41 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun handleRequest_newFreeformTaskLaunch_cascadeApplied() { + assumeTrue(ENABLE_SHELL_TRANSITIONS) + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + setUpFreeformTask(bounds = DEFAULT_LANDSCAPE_BOUNDS) + val freeformTask = setUpFreeformTask(bounds = DEFAULT_LANDSCAPE_BOUNDS, active = false) + + val wct = controller.handleRequest(Binder(), createTransition(freeformTask)) + + assertNotNull(wct, "should handle request") + val finalBounds = findBoundsChange(wct, freeformTask) + assertThat(stableBounds.getDesktopTaskPosition(finalBounds!!)) + .isEqualTo(DesktopTaskPosition.BottomRight) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) + fun handleRequest_freeformTaskAlreadyExistsInDesktopMode_cascadeNotApplied() { + assumeTrue(ENABLE_SHELL_TRANSITIONS) + setUpLandscapeDisplay() + val stableBounds = Rect() + displayLayout.getStableBoundsForDesktopMode(stableBounds) + + setUpFreeformTask(bounds = DEFAULT_LANDSCAPE_BOUNDS) + val freeformTask = setUpFreeformTask(bounds = DEFAULT_LANDSCAPE_BOUNDS) + + val wct = controller.handleRequest(Binder(), createTransition(freeformTask)) + + assertNull(wct, "should not handle request") + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS) fun addMoveToDesktopChanges_positionBottomRight() { setUpLandscapeDisplay() val stableBounds = Rect() @@ -832,6 +869,18 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + fun addMoveToDesktopChanges_landscapeDevice_portraitResizableApp_aspectRatioOverridden() { + setUpLandscapeDisplay() + val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_PORTRAIT, + shouldLetterbox = true, aspectRatioOverrideApplied = true) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_PORTRAIT_BOUNDS) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) fun addMoveToDesktopChanges_portraitDevice_userFullscreenOverride_defaultPortraitBounds() { setUpPortraitDisplay() val task = setUpFullscreenTask(enableUserFullscreenOverride = true) @@ -853,6 +902,19 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + fun addMoveToDesktopChanges_portraitDevice_landscapeResizableApp_aspectRatioOverridden() { + setUpPortraitDisplay() + val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_LANDSCAPE, + deviceOrientation = ORIENTATION_PORTRAIT, + shouldLetterbox = true, aspectRatioOverrideApplied = true) + val wct = WindowContainerTransaction() + controller.addMoveToDesktopChanges(wct, task) + + assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_LANDSCAPE_BOUNDS) + } + + @Test fun moveToDesktop_tdaFullscreen_windowingModeSetToFreeform() { val task = setUpFullscreenTask() val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!! @@ -1784,6 +1846,19 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test + @EnableFlags( + Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, + ) + fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_notInDesktop_doesNotHandle() { + val task = setUpFreeformTask() + markTaskHidden(task) + + val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) + + assertNull(result, "Should not handle request") + } + + @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_singleTaskNoToken_noBackNav_doesNotHandle() { @@ -2189,27 +2264,6 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test - fun desktopTasksVisibilityChange_visible_setLaunchAdjacentDisabled() { - val task = setUpFreeformTask() - clearInvocations(launchAdjacentController) - - markTaskVisible(task) - shellExecutor.flushAll() - verify(launchAdjacentController).launchAdjacentEnabled = false - } - - @Test - fun desktopTasksVisibilityChange_invisible_setLaunchAdjacentEnabled() { - val task = setUpFreeformTask() - markTaskVisible(task) - clearInvocations(launchAdjacentController) - - markTaskHidden(task) - shellExecutor.flushAll() - verify(launchAdjacentController).launchAdjacentEnabled = true - } - - @Test fun moveFocusedTaskToDesktop_fullscreenTaskIsMovedToDesktop() { val task1 = setUpFullscreenTask() val task2 = setUpFullscreenTask() @@ -2314,7 +2368,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_undefinedOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask() @@ -2330,7 +2384,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_landscapeOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_LANDSCAPE) @@ -2346,7 +2400,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_portraitOrientation_resizablePortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2363,7 +2417,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_unResizable_landscapeOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2380,7 +2434,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_unResizable_portraitOrientation_unResizablePortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2400,7 +2454,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_undefinedOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask(deviceOrientation = ORIENTATION_PORTRAIT) @@ -2416,7 +2470,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_portraitOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2435,7 +2489,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_landscapeOrientation_resizableLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2455,7 +2509,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_unResizable_portraitOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2475,7 +2529,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_unResizable_landscapeOrientation_unResizableLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2532,7 +2586,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val currentDragBounds = Rect(100, 200, 500, 1000) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR) spyController.onDragPositioningEnd( @@ -2816,14 +2870,17 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpFreeformTask( displayId: Int = DEFAULT_DISPLAY, - bounds: Rect? = null + bounds: Rect? = null, + active: Boolean = true ): RunningTaskInfo { val task = createFreeformTask(displayId, bounds) val activityInfo = ActivityInfo() task.topActivityInfo = activityInfo whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) - taskRepository.addActiveTask(displayId, task.taskId) - taskRepository.updateTaskVisibility(displayId, task.taskId, visible = true) + if (active) { + taskRepository.addActiveTask(displayId, task.taskId) + taskRepository.updateTaskVisibility(displayId, task.taskId, visible = true) + } taskRepository.addOrMoveFreeformTaskToTop(displayId, task.taskId) runningTasks.add(task) return task @@ -2845,7 +2902,8 @@ class DesktopTasksControllerTest : ShellTestCase() { shouldLetterbox: Boolean = false, gravity: Int = Gravity.NO_GRAVITY, enableUserFullscreenOverride: Boolean = false, - enableSystemFullscreenOverride: Boolean = false + enableSystemFullscreenOverride: Boolean = false, + aspectRatioOverrideApplied: Boolean = false ): RunningTaskInfo { val task = createFullscreenTask(displayId) val activityInfo = ActivityInfo() @@ -2860,6 +2918,7 @@ class DesktopTasksControllerTest : ShellTestCase() { appCompatTaskInfo.isSystemFullscreenOverrideEnabled = enableSystemFullscreenOverride if (shouldLetterbox) { + appCompatTaskInfo.setHasMinAspectRatioOverride(aspectRatioOverrideApplied) if (deviceOrientation == ORIENTATION_LANDSCAPE && screenOrientation == SCREEN_ORIENTATION_PORTRAIT) { // Letterbox to portrait size diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt index c97bcfb1a4cb..16a234b9e2f2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt @@ -20,8 +20,8 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestRunningTaskInfoBuilder -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java index 97fa8d6ceca9..645b296930f8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java @@ -27,9 +27,9 @@ import static android.content.ClipDescription.MIMETYPE_TEXT_INTENT; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java index 6ec6bed860bd..763d0153071e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.app.ActivityManager; +import android.view.SurfaceControl; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -35,6 +36,7 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; +import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; @@ -65,7 +67,11 @@ public final class FreeformTaskListenerTests extends ShellTestCase { @Mock private WindowDecorViewModel mWindowDecorViewModel; @Mock + private SurfaceControl mMockSurfaceControl; + @Mock private DesktopModeTaskRepository mDesktopModeTaskRepository; + @Mock + private LaunchAdjacentController mLaunchAdjacentController; private FreeformTaskListener mFreeformTaskListener; private StaticMockitoSession mMockitoSession; @@ -80,6 +86,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mShellInit, mTaskOrganizer, Optional.of(mDesktopModeTaskRepository), + mLaunchAdjacentController, mWindowDecorViewModel); } @@ -107,6 +114,31 @@ public final class FreeformTaskListenerTests extends ShellTestCase { .addOrMoveFreeformTaskToTop(fullscreenTask.displayId, fullscreenTask.taskId); } + @Test + public void testVisibilityTaskChanged_visible_setLaunchAdjacentDisabled() { + ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder() + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + task.isVisible = true; + + mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); + + verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(false); + } + + @Test + public void testVisibilityTaskChanged_NotVisible_setLaunchAdjacentEnabled() { + ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder() + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + task.isVisible = true; + + mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); + + task.isVisible = false; + mFreeformTaskListener.onTaskInfoChanged(task); + + verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(true); + } + @After public void tearDown() { mMockitoSession.finishMocking(); 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 8ad3d2a72617..7d063a0a773f 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 @@ -48,10 +48,10 @@ 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.shared.ShellSharedConstants; 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.ShellSharedConstants; import org.junit.Before; import org.junit.Test; 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 75d21457b60b..6ddb6781c80c 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 @@ -67,10 +67,10 @@ 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.pip.PipTransitionState; +import com.android.wm.shell.shared.ShellSharedConstants; 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.ShellSharedConstants; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/PipTransitionStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTransitionStateTest.java index f3f3c37b645d..571ae93e1aec 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/PipTransitionStateTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTransitionStateTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip2; +package com.android.wm.shell.pip2.phone; import android.os.Bundle; import android.os.Handler; @@ -22,8 +22,6 @@ import android.os.Parcelable; import android.testing.AndroidTestingRunner; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.pip.PhoneSizeSpecSource; -import com.android.wm.shell.pip2.phone.PipTransitionState; import junit.framework.Assert; @@ -33,7 +31,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; /** - * Unit test against {@link PhoneSizeSpecSource}. + * Unit test against {@link PipTransitionState}. * * This test mocks the PiP2 flag to be true. */ diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipUiStateChangeControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipUiStateChangeControllerTests.java new file mode 100644 index 000000000000..82cdfd52d2db --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipUiStateChangeControllerTests.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip2.phone; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import android.app.Flags; +import android.app.PictureInPictureUiState; +import android.os.Bundle; +import android.platform.test.annotations.EnableFlags; +import android.testing.AndroidTestingRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.function.Consumer; + +/** + * Unit test against {@link PipUiStateChangeController}. + */ +@RunWith(AndroidTestingRunner.class) +public class PipUiStateChangeControllerTests { + + @Mock + private PipTransitionState mPipTransitionState; + + private Consumer<PictureInPictureUiState> mPictureInPictureUiStateConsumer; + private ArgumentCaptor<PictureInPictureUiState> mArgumentCaptor; + + private PipUiStateChangeController mPipUiStateChangeController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mPipUiStateChangeController = new PipUiStateChangeController(mPipTransitionState); + mPictureInPictureUiStateConsumer = spy(pictureInPictureUiState -> {}); + mPipUiStateChangeController.setPictureInPictureUiStateConsumer( + mPictureInPictureUiStateConsumer); + mArgumentCaptor = ArgumentCaptor.forClass(PictureInPictureUiState.class); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING) + public void onPipTransitionStateChanged_swipePipStart_callbackIsTransitioningToPipTrue() { + when(mPipTransitionState.isInSwipePipToHomeTransition()).thenReturn(true); + + mPipUiStateChangeController.onPipTransitionStateChanged( + PipTransitionState.UNDEFINED, PipTransitionState.SWIPING_TO_PIP, Bundle.EMPTY); + + verify(mPictureInPictureUiStateConsumer).accept(mArgumentCaptor.capture()); + assertTrue(mArgumentCaptor.getValue().isTransitioningToPip()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING) + public void onPipTransitionStateChanged_swipePipOngoing_noCallbackIsTransitioningToPip() { + when(mPipTransitionState.isInSwipePipToHomeTransition()).thenReturn(true); + + mPipUiStateChangeController.onPipTransitionStateChanged( + PipTransitionState.SWIPING_TO_PIP, PipTransitionState.ENTERING_PIP, Bundle.EMPTY); + + verifyZeroInteractions(mPictureInPictureUiStateConsumer); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING) + public void onPipTransitionStateChanged_swipePipFinish_callbackIsTransitioningToPipFalse() { + when(mPipTransitionState.isInSwipePipToHomeTransition()).thenReturn(true); + + mPipUiStateChangeController.onPipTransitionStateChanged( + PipTransitionState.SWIPING_TO_PIP, PipTransitionState.ENTERED_PIP, Bundle.EMPTY); + + verify(mPictureInPictureUiStateConsumer).accept(mArgumentCaptor.capture()); + assertFalse(mArgumentCaptor.getValue().isTransitioningToPip()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING) + public void onPipTransitionStateChanged_tapHomeStart_callbackIsTransitioningToPipTrue() { + when(mPipTransitionState.isInSwipePipToHomeTransition()).thenReturn(false); + + mPipUiStateChangeController.onPipTransitionStateChanged( + PipTransitionState.UNDEFINED, PipTransitionState.ENTERING_PIP, Bundle.EMPTY); + + verify(mPictureInPictureUiStateConsumer).accept(mArgumentCaptor.capture()); + assertTrue(mArgumentCaptor.getValue().isTransitioningToPip()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING) + public void onPipTransitionStateChanged_tapHomeFinish_callbackIsTransitioningToPipFalse() { + when(mPipTransitionState.isInSwipePipToHomeTransition()).thenReturn(false); + + mPipUiStateChangeController.onPipTransitionStateChanged( + PipTransitionState.ENTERING_PIP, PipTransitionState.ENTERED_PIP, Bundle.EMPTY); + + verify(mPictureInPictureUiStateConsumer).accept(mArgumentCaptor.capture()); + assertFalse(mArgumentCaptor.getValue().isTransitioningToPip()); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt index 15b73c541ed8..6736593bba5b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.recents import android.app.ActivityManager -import android.app.ActivityManager.RecentTaskInfo import android.graphics.Rect import android.os.Parcel import android.testing.AndroidTestingRunner @@ -25,7 +24,7 @@ import android.window.IWindowContainerToken import android.window.WindowContainerToken import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase -import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50 +import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50 import com.android.wm.shell.util.GroupedRecentTaskInfo import com.android.wm.shell.util.GroupedRecentTaskInfo.CREATOR import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index a0aab2e6c8a4..e1fe4e9054c0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -22,7 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -68,11 +68,11 @@ import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.shared.ShellSharedConstants; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; 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.ShellSharedConstants; import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.SplitBounds; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/SplitBoundsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/SplitBoundsTest.java index b790aee6fb0e..bfb760b6fc8c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/SplitBoundsTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/SplitBoundsTest.java @@ -1,6 +1,6 @@ package com.android.wm.shell.recents; -import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/magnetictarget/MagnetizedObjectTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/magnetictarget/MagnetizedObjectTest.kt index 8bb182de7668..8711ee01601c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/magnetictarget/MagnetizedObjectTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/magnetictarget/MagnetizedObjectTest.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.wm.shell.common.magnetictarget +package com.android.wm.shell.shared.magnetictarget import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -33,13 +33,13 @@ import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyFloat import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.Mockito.doAnswer import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.Mockito.`when` @TestableLooper.RunWithLooper @RunWith(AndroidTestingRunner::class) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/split/SplitScreenConstantsTest.kt index fe261107d65b..19c18be44ab1 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/split/SplitScreenConstantsTest.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.common.split import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.wm.shell.shared.split.SplitScreenConstants import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith 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 1c5d5e963156..9260a07fd945 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 @@ -23,8 +23,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeTrue; @@ -70,14 +70,14 @@ import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.common.MultiInstanceHelper; 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.desktopmode.DesktopTasksController; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.ShellSharedConstants; +import com.android.wm.shell.shared.TransactionPool; 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.ShellSharedConstants; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java index 29d3fb4cc04e..aa96c45489dd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java @@ -35,9 +35,9 @@ import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.LaunchAdjacentController; 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.common.split.SplitLayout; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; 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 1990fe7946e9..abe3dcc1eb80 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 @@ -76,9 +76,9 @@ import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.LaunchAdjacentController; 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.common.split.SplitDecorManager; import com.android.wm.shell.common.split.SplitLayout; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.TestRemoteTransition; import com.android.wm.shell.transition.TransitionInfoBuilder; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index ff6c7eeb9d1a..0054cb6ccc8c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -19,13 +19,12 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; -import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; -import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS; import static com.google.common.truth.Truth.assertThat; @@ -69,9 +68,9 @@ import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.LaunchAdjacentController; 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.common.split.SplitDecorManager; import com.android.wm.shell.common.split.SplitLayout; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; 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 af6c077303c4..5f7542332c80 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 @@ -74,7 +74,7 @@ import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.HandlerExecutor; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java index ff76a2f13527..7fd1c11e61ae 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java @@ -42,11 +42,11 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.ShellSharedConstants; +import com.android.wm.shell.shared.TransactionPool; 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.ShellSharedConstants; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java index 6bc7e499159c..0c18229f38d0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java @@ -48,7 +48,7 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayController; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import org.junit.After; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java index 0db10ef65a74..d2adae181f7b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java @@ -51,8 +51,8 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.shared.IHomeTransitionListener; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/MockTransactionPool.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/MockTransactionPool.java index 574a87ac4b17..a5a27e2568a3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/MockTransactionPool.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/MockTransactionPool.java @@ -21,7 +21,7 @@ import static org.mockito.Mockito.mock; import android.view.SurfaceControl; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.util.StubTransaction; public class MockTransactionPool extends TransactionPool { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index 81e6d071045a..7c63fdad660a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -107,12 +107,12 @@ import com.android.wm.shell.TestShellExecutor; 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.TransactionPool; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.recents.RecentsTransitionHandler; +import com.android.wm.shell.shared.ShellSharedConstants; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; -import com.android.wm.shell.sysui.ShellSharedConstants; import com.android.wm.shell.util.StubTransaction; import org.junit.Before; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java index 8196c5ab08e4..8fe0c386b7fe 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java @@ -35,7 +35,7 @@ import android.view.SurfaceControl.Transaction; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.TestShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.unfold.animation.UnfoldTaskAnimator; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java index acc0bce5cce9..cf2de91bad88 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java @@ -40,7 +40,7 @@ import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.TransitionInfoBuilder; import com.android.wm.shell.transition.Transitions; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index fa905e2e5c37..4d6b3b907a65 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -56,6 +56,7 @@ import android.view.SurfaceControl import android.view.SurfaceView import android.view.View import android.view.WindowInsets.Type.statusBars +import android.widget.Toast import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.HierarchyOp import androidx.test.filters.SmallTest @@ -93,6 +94,8 @@ import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopM import java.util.Optional import java.util.function.Consumer import java.util.function.Supplier +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue import org.junit.After import org.junit.Assert.assertEquals import org.junit.Before @@ -117,8 +120,7 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.whenever import org.mockito.quality.Strictness -import junit.framework.Assert.assertFalse -import junit.framework.Assert.assertTrue + /** * Tests of [DesktopModeWindowDecorViewModel] @@ -158,6 +160,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @Mock private lateinit var mockWindowManager: IWindowManager @Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor @Mock private lateinit var mockGenericLinksParser: AppToWebGenericLinksParser + @Mock private lateinit var mockToast: Toast private val bgExecutor = TestShellExecutor() @Mock private lateinit var mockMultiInstanceHelper: MultiInstanceHelper private lateinit var spyContext: TestableContext @@ -181,6 +184,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { .strictness(Strictness.LENIENT) .spyStatic(DesktopModeStatus::class.java) .spyStatic(DragPositioningCallbackUtility::class.java) + .spyStatic(Toast::class.java) .startMocking() doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(Mockito.any()) } @@ -218,6 +222,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { whenever(mockDisplayLayout.stableInsets()).thenReturn(STABLE_INSETS) whenever(mockInputMonitorFactory.create(any(), any())).thenReturn(mockInputMonitor) + doReturn(mockToast).`when` { Toast.makeText(any(), anyInt(), anyInt()) } + // InputChannel cannot be mocked because it passes to InputEventReceiver. val inputChannels = InputChannel.openInputChannelPair(TAG) inputChannels.first().dispose() @@ -284,11 +290,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @Test @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR) fun testCreateAndDisposeEventReceiver() { - val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - setUpMockDecorationForTask(task) - - onTaskOpening(task) - desktopModeWindowDecorViewModel.destroyWindowDecoration(task) + val decor = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_FREEFORM) + desktopModeWindowDecorViewModel.destroyWindowDecoration(decor.mTaskInfo) verify(mockInputMonitorFactory).create(any(), any()) verify(mockInputMonitor).dispose() @@ -357,16 +360,14 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { } @Test - fun testCloseButtonInFreeform() { - val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val windowDecor = setUpMockDecorationForTask(task) - - onTaskOpening(task) - val onClickListenerCaptor = argumentCaptor<View.OnClickListener>() - verify(windowDecor).setCaptionListeners( - onClickListenerCaptor.capture(), any(), any(), any()) + fun testCloseButtonInFreeform_closeWindow() { + val onClickListenerCaptor = forClass(View.OnClickListener::class.java) + as ArgumentCaptor<View.OnClickListener> + val decor = createOpenTaskDecoration( + windowingMode = WINDOWING_MODE_FREEFORM, + onCaptionButtonClickListener = onClickListenerCaptor + ) - val onClickListener = onClickListenerCaptor.firstValue val view = mock(View::class.java) whenever(view.id).thenReturn(R.id.close_window) @@ -374,7 +375,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { desktopModeWindowDecorViewModel .setFreeformTaskTransitionStarter(freeformTaskTransitionStarter) - onClickListener.onClick(view) + onClickListenerCaptor.value.onClick(view) val transactionCaptor = argumentCaptor<WindowContainerTransaction>() verify(freeformTaskTransitionStarter).startRemoveTransition(transactionCaptor.capture()) @@ -383,7 +384,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { assertEquals(1, wct.getHierarchyOps().size) assertEquals(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK, wct.getHierarchyOps().get(0).getType()) - assertEquals(task.token.asBinder(), wct.getHierarchyOps().get(0).getContainer()) + assertEquals(decor.mTaskInfo.token.asBinder(), wct.getHierarchyOps().get(0).getContainer()) } @Test @@ -458,15 +459,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @Test fun testKeyguardState_notifiesAllDecors() { - val task1 = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration1 = setUpMockDecorationForTask(task1) - onTaskOpening(task1) - val task2 = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration2 = setUpMockDecorationForTask(task2) - onTaskOpening(task2) - val task3 = createTask(windowingMode = WINDOWING_MODE_FREEFORM) - val decoration3 = setUpMockDecorationForTask(task3) - onTaskOpening(task3) + val decoration1 = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_FREEFORM) + val decoration2 = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_FREEFORM) + val decoration3 = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_FREEFORM) desktopModeOnKeyguardChangedListener .onKeyguardVisibilityChanged(true /* visible */, true /* occluded */, @@ -625,6 +620,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { verify(mockDesktopTasksController, never()) .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT) + verify(mockToast).show() } @Test @@ -690,6 +686,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { verify(mockDesktopTasksController, never()) .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT) + verify(mockToast).show() } @Test @@ -1009,6 +1006,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>, onOpenInBrowserClickListener: ArgumentCaptor<Consumer<Uri>> = forClass(Consumer::class.java) as ArgumentCaptor<Consumer<Uri>>, + onCaptionButtonClickListener: ArgumentCaptor<View.OnClickListener> = + forClass(View.OnClickListener::class.java) as ArgumentCaptor<View.OnClickListener> ): DesktopModeWindowDecoration { val decor = setUpMockDecorationForTask(createTask(windowingMode = windowingMode)) onTaskOpening(decor.mTaskInfo) @@ -1019,6 +1018,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { verify(decor).setOnToFullscreenClickListener(onToFullscreenClickListenerCaptor.capture()) verify(decor).setOnToSplitScreenClickListener(onToSplitScreenClickListenerCaptor.capture()) verify(decor).setOpenInBrowserClickListener(onOpenInBrowserClickListener.capture()) + verify(decor).setCaptionListeners( + onCaptionButtonClickListener.capture(), any(), any(), any()) return decor } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt index e52971120478..1f33ae69b724 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt @@ -93,7 +93,7 @@ class DragPositioningCallbackUtilityTest { fun setup() { MockitoAnnotations.initMocks(this) mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT) - .spyStatic(DesktopModeStatus::class.java).startMocking() + .spyStatic(DesktopModeStatus::class.java).startMocking() whenever(taskToken.asBinder()).thenReturn(taskBinder) whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout) @@ -108,9 +108,9 @@ class DragPositioningCallbackUtilityTest { whenever(mockContext.getResources()).thenReturn(mockResources) whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width)) - .thenReturn(DESKTOP_MODE_MIN_WIDTH) + .thenReturn(DESKTOP_MODE_MIN_WIDTH) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height)) - .thenReturn(DESKTOP_MODE_MIN_HEIGHT) + .thenReturn(DESKTOP_MODE_MIN_HEIGHT) whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID } } @@ -129,9 +129,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.top.toFloat() + 95 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) @@ -149,9 +151,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.top.toFloat() + 5 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 5) @@ -169,9 +173,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.top.toFloat() + 105 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) @@ -189,9 +195,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.top.toFloat() + 80 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 80) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) @@ -208,9 +216,11 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) @@ -221,52 +231,95 @@ class DragPositioningCallbackUtilityTest { fun testDragEndSnapsTaskBoundsWhenOutsideValidDragArea() { val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) - val validDragArea = Rect(DISPLAY_BOUNDS.left - 100, + val validDragArea = Rect( + DISPLAY_BOUNDS.left - 100, STABLE_BOUNDS.top, DISPLAY_BOUNDS.right - 100, - DISPLAY_BOUNDS.bottom - 100) + DISPLAY_BOUNDS.bottom - 100 + ) - DragPositioningCallbackUtility.updateTaskBounds(repositionTaskBounds, STARTING_BOUNDS, - startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat()) - DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(repositionTaskBounds, - validDragArea) + DragPositioningCallbackUtility.updateTaskBounds( + repositionTaskBounds, STARTING_BOUNDS, + startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat() + ) + DragPositioningCallbackUtility.snapTaskBoundsIfNecessary( + repositionTaskBounds, + validDragArea + ) assertThat(repositionTaskBounds.left).isEqualTo(validDragArea.left) assertThat(repositionTaskBounds.top).isEqualTo(validDragArea.bottom) assertThat(repositionTaskBounds.right) - .isEqualTo(validDragArea.left + STARTING_BOUNDS.width()) + .isEqualTo(validDragArea.left + STARTING_BOUNDS.width()) assertThat(repositionTaskBounds.bottom) - .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height()) + .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height()) } @Test fun testChangeBounds_toDisallowedBounds_freezesAtLimit() { - val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), - STARTING_BOUNDS.bottom.toFloat()) + val startingPoint = PointF( + STARTING_BOUNDS.right.toFloat(), + STARTING_BOUNDS.bottom.toFloat() + ) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Initial resize to width and height 110px. var newX = STARTING_BOUNDS.right.toFloat() + 10 var newY = STARTING_BOUNDS.bottom.toFloat() + 10 var delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, - repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration)) + assertTrue( + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, + mockWindowDecoration + ) + ) // Resize width to 120px, height to disallowed area which should not result in a change. newX += 10 newY = DISALLOWED_RESIZE_AREA.top.toFloat() delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, - repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration)) + assertTrue( + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, + mockWindowDecoration + ) + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right + 20) - assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom + 10) + assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom) + } + + + @Test + fun testChangeBounds_beyondStableBounds_freezesAtStableBounds() { + val startingPoint = PointF( + STARTING_BOUNDS.right.toFloat(), + STARTING_BOUNDS.bottom.toFloat() + ) + val repositionTaskBounds = Rect(STARTING_BOUNDS) + + // Resize to beyond stable bounds. + val newX = STARTING_BOUNDS.right.toFloat() + STABLE_BOUNDS.width() + val newY = STARTING_BOUNDS.bottom.toFloat() + STABLE_BOUNDS.height() + + val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) + assertTrue( + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, + mockWindowDecoration + ) + ) + assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) + assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) + assertThat(repositionTaskBounds.right).isEqualTo(STABLE_BOUNDS.right) + assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() { - doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) } + doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) } initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) @@ -277,9 +330,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) @@ -289,7 +344,7 @@ class DragPositioningCallbackUtilityTest { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() { - doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) } + doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) } initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) @@ -300,9 +355,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.bottom.toFloat() - 80 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) @@ -321,9 +378,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) @@ -342,9 +401,11 @@ class DragPositioningCallbackUtilityTest { val newY = STARTING_BOUNDS.bottom.toFloat() - 50 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, - mockWindowDecoration) + mockWindowDecoration + ) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 50) @@ -355,8 +416,10 @@ class DragPositioningCallbackUtilityTest { @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun testChangeBounds_windowSizeExceedsStableBounds_shouldBeAllowedToChangeBounds() { val startingPoint = - PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(), - OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()) + PointF( + OFF_CENTER_STARTING_BOUNDS.right.toFloat(), + OFF_CENTER_STARTING_BOUNDS.bottom.toFloat() + ) val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS) // Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach // the disallowed drag area. @@ -365,9 +428,11 @@ class DragPositioningCallbackUtilityTest { val newY = STABLE_BOUNDS.bottom.toFloat() - offset val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta, - mockDisplayController, mockWindowDecoration) + mockDisplayController, mockWindowDecoration + ) assertThat(repositionTaskBounds.width()).isGreaterThan(STABLE_BOUNDS.right) assertThat(repositionTaskBounds.height()).isGreaterThan(STABLE_BOUNDS.bottom) } @@ -375,10 +440,12 @@ class DragPositioningCallbackUtilityTest { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun testChangeBoundsInDesktopMode_windowSizeExceedsStableBounds_shouldBeLimitedToDisplaySize() { - doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) } + doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) } val startingPoint = - PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(), - OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()) + PointF( + OFF_CENTER_STARTING_BOUNDS.right.toFloat(), + OFF_CENTER_STARTING_BOUNDS.bottom.toFloat() + ) val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS) // Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach // the disallowed drag area. @@ -387,9 +454,11 @@ class DragPositioningCallbackUtilityTest { val newY = STABLE_BOUNDS.bottom.toFloat() - offset val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) - DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, + DragPositioningCallbackUtility.changeBounds( + CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta, - mockDisplayController, mockWindowDecoration) + mockDisplayController, mockWindowDecoration + ) assertThat(repositionTaskBounds.width()).isLessThan(STABLE_BOUNDS.right) assertThat(repositionTaskBounds.height()).isLessThan(STABLE_BOUNDS.bottom) } @@ -423,7 +492,8 @@ class DragPositioningCallbackUtilityTest { DISPLAY_BOUNDS.left, DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT, DISPLAY_BOUNDS.right, - DISPLAY_BOUNDS.bottom) + DISPLAY_BOUNDS.bottom + ) private val STABLE_BOUNDS = Rect( DISPLAY_BOUNDS.left, DISPLAY_BOUNDS.top, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java index d8f395d76b39..1691f077a030 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java @@ -45,6 +45,9 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.List; + /** * Tests for {@link DragResizeWindowGeometry}. * @@ -57,11 +60,12 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { private static final Size TASK_SIZE = new Size(500, 1000); private static final int TASK_CORNER_RADIUS = 10; private static final int EDGE_RESIZE_THICKNESS = 12; + private static final int EDGE_RESIZE_HANDLE_INSET = 4; private static final int FINE_CORNER_SIZE = EDGE_RESIZE_THICKNESS * 2 + 10; private static final int LARGE_CORNER_SIZE = FINE_CORNER_SIZE + 10; private static final DragResizeWindowGeometry GEOMETRY = new DragResizeWindowGeometry( - TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, - LARGE_CORNER_SIZE); + TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, EDGE_RESIZE_HANDLE_INSET, + FINE_CORNER_SIZE, LARGE_CORNER_SIZE); // Points in the edge resize handle. Note that coordinates start from the top left. private static final Point TOP_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2, -EDGE_RESIZE_THICKNESS / 2); @@ -71,6 +75,16 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { TASK_SIZE.getWidth() + EDGE_RESIZE_THICKNESS / 2, TASK_SIZE.getHeight() / 2); private static final Point BOTTOM_EDGE_POINT = new Point(TASK_SIZE.getWidth() / 2, TASK_SIZE.getHeight() + EDGE_RESIZE_THICKNESS / 2); + // Points in the inset of the task bounds still within the edge resize handle. + // Note that coordinates start from the top left. + private static final Point TOP_INSET_POINT = new Point(TASK_SIZE.getWidth() / 2, + EDGE_RESIZE_HANDLE_INSET / 2); + private static final Point LEFT_INSET_POINT = new Point(EDGE_RESIZE_HANDLE_INSET / 2, + TASK_SIZE.getHeight() / 2); + private static final Point RIGHT_INSET_POINT = new Point( + TASK_SIZE.getWidth() - EDGE_RESIZE_HANDLE_INSET / 2, TASK_SIZE.getHeight() / 2); + private static final Point BOTTOM_INSET_POINT = new Point(TASK_SIZE.getWidth() / 2, + TASK_SIZE.getHeight() - EDGE_RESIZE_HANDLE_INSET / 2); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -85,18 +99,23 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { .addEqualityGroup( GEOMETRY, new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE, - EDGE_RESIZE_THICKNESS, FINE_CORNER_SIZE, LARGE_CORNER_SIZE)) + EDGE_RESIZE_THICKNESS, EDGE_RESIZE_HANDLE_INSET, FINE_CORNER_SIZE, + LARGE_CORNER_SIZE)) .addEqualityGroup( new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE, - EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE), + EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET, + FINE_CORNER_SIZE, LARGE_CORNER_SIZE), new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE, - EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, LARGE_CORNER_SIZE)) + EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET, + FINE_CORNER_SIZE, LARGE_CORNER_SIZE)) .addEqualityGroup( new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE, - EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, + EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET, + FINE_CORNER_SIZE, LARGE_CORNER_SIZE + 5), new DragResizeWindowGeometry(TASK_CORNER_RADIUS, TASK_SIZE, - EDGE_RESIZE_THICKNESS + 10, FINE_CORNER_SIZE, + EDGE_RESIZE_THICKNESS + 10, EDGE_RESIZE_HANDLE_INSET, + FINE_CORNER_SIZE, LARGE_CORNER_SIZE + 5)) .testEquals(); } @@ -127,7 +146,7 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isTrue(); // Vertically along the edge is not contained. assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isFalse(); - assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isFalse(); + assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS + 10)).isFalse(); } private static void verifyVerticalEdge(@NonNull Region region, @NonNull Point point) { @@ -188,18 +207,18 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { } private void validateCtrlTypeForEdges(boolean isTouchscreen, boolean isEdgeResizePermitted) { - assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted, - LEFT_EDGE_POINT.x, LEFT_EDGE_POINT.y)).isEqualTo( - isEdgeResizePermitted ? CTRL_TYPE_LEFT : CTRL_TYPE_UNDEFINED); - assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted, - TOP_EDGE_POINT.x, TOP_EDGE_POINT.y)).isEqualTo( - isEdgeResizePermitted ? CTRL_TYPE_TOP : CTRL_TYPE_UNDEFINED); - assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted, - RIGHT_EDGE_POINT.x, RIGHT_EDGE_POINT.y)).isEqualTo( - isEdgeResizePermitted ? CTRL_TYPE_RIGHT : CTRL_TYPE_UNDEFINED); - assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted, - BOTTOM_EDGE_POINT.x, BOTTOM_EDGE_POINT.y)).isEqualTo( - isEdgeResizePermitted ? CTRL_TYPE_BOTTOM : CTRL_TYPE_UNDEFINED); + List<Point> points = Arrays.asList(LEFT_EDGE_POINT, TOP_EDGE_POINT, RIGHT_EDGE_POINT, + BOTTOM_EDGE_POINT, LEFT_INSET_POINT, TOP_INSET_POINT, RIGHT_INSET_POINT, + BOTTOM_INSET_POINT); + List<Integer> expectedCtrlType = Arrays.asList(CTRL_TYPE_LEFT, CTRL_TYPE_TOP, + CTRL_TYPE_RIGHT, CTRL_TYPE_BOTTOM, CTRL_TYPE_LEFT, CTRL_TYPE_TOP, CTRL_TYPE_RIGHT, + CTRL_TYPE_BOTTOM); + + for (int i = 0; i < points.size(); i++) { + assertThat(GEOMETRY.calculateCtrlType(mContext, isTouchscreen, isEdgeResizePermitted, + points.get(i).x, points.get(i).y)).isEqualTo( + isEdgeResizePermitted ? expectedCtrlType.get(i) : CTRL_TYPE_UNDEFINED); + } } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt index 2ce59ff0a4a9..3a3e965b625e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt @@ -678,6 +678,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM) val rectAfterDrag = Rect(STARTING_BOUNDS) rectAfterDrag.right += 2000 + rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom // First drag; we should fetch stable bounds. verify(mockDisplayLayout, Mockito.times(1)).getStableBounds(any()) verify(mockShellTaskOrganizer).applyTransaction(argThat { wct -> @@ -705,8 +706,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(), STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000, CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM) - rectAfterDrag.right -= 2000 - rectAfterDrag.bottom += 2000 + rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right + rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000 verify(mockShellTaskOrganizer).applyTransaction(argThat { wct -> return@argThat wct.changes.any { (token, change) -> diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt index a1c794748c21..627dfe718521 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt @@ -41,9 +41,9 @@ import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestRunningTaskInfoBuilder import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt index 08a6e1ba676b..6ae16edaf3df 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt @@ -372,6 +372,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() { CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM) val rectAfterDrag = Rect(STARTING_BOUNDS) rectAfterDrag.right += 2000 + rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom // First drag; we should fetch stable bounds. verify(mockDisplayLayout, times(1)).getStableBounds(any()) verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct -> @@ -396,8 +397,8 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() { performDrag(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(), STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000, CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM) - rectAfterDrag.right -= 2000 - rectAfterDrag.bottom += 2000 + rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right + rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000 verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct -> return@argThat wct.changes.any { (token, change) -> diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 822a387351e3..0fa31c7a832e 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -107,7 +107,7 @@ AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& co } AssetManager2::AssetManager2() { - configurations_.resize(1); + configurations_.emplace_back(); } bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) { @@ -438,8 +438,8 @@ bool AssetManager2::ContainsAllocatedTable() const { return false; } -void AssetManager2::SetConfigurations(std::vector<ResTable_config> configurations, - bool force_refresh) { +void AssetManager2::SetConfigurations(std::span<const ResTable_config> configurations, + bool force_refresh) { int diff = 0; if (force_refresh) { diff = -1; @@ -452,8 +452,10 @@ void AssetManager2::SetConfigurations(std::vector<ResTable_config> configuration } } } - configurations_ = std::move(configurations); - + configurations_.clear(); + for (auto&& config : configurations) { + configurations_.emplace_back(config); + } if (diff) { RebuildFilterList(); InvalidateCaches(static_cast<uint32_t>(diff)); diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp index 8ddc57240129..49ee8f7ac4eb 100644 --- a/libs/androidfw/PosixUtils.cpp +++ b/libs/androidfw/PosixUtils.cpp @@ -119,7 +119,7 @@ ProcResult ExecuteBinary(const std::vector<std::string>& argv) { auto err = ReadFile(stderr[0]); result.stderr_str = err ? std::move(*err) : ""; close(stderr[0]); - return std::move(result); + return result; } } diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index ac46bc5c179f..0fdeefa09e26 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -32,6 +32,7 @@ #include "androidfw/AssetManager.h" #include "androidfw/ResourceTypes.h" #include "androidfw/Util.h" +#include "ftl/small_vector.h" namespace android { @@ -159,9 +160,10 @@ class AssetManager2 { // Sets/resets the configuration for this AssetManager. This will cause all // caches that are related to the configuration change to be invalidated. - void SetConfigurations(std::vector<ResTable_config> configurations, bool force_refresh = false); + void SetConfigurations(std::span<const ResTable_config> configurations, + bool force_refresh = false); - inline const std::vector<ResTable_config>& GetConfigurations() const { + std::span<const ResTable_config> GetConfigurations() const { return configurations_; } @@ -470,13 +472,13 @@ class AssetManager2 { // An array mapping package ID to index into package_groups. This keeps the lookup fast // without taking too much memory. - std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_; + std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_ = {}; - uint32_t default_locale_; + uint32_t default_locale_ = 0; // The current configurations set for this AssetManager. When this changes, cached resources // may need to be purged. - std::vector<ResTable_config> configurations_; + ftl::SmallVector<ResTable_config, 1> configurations_; // Cached set of bags. These are cached because they can inherit keys from parent bags, // which involves some calculation. diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index c62f095e9dac..3f228841f6ba 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -113,7 +113,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { desired_config.language[1] = 'e'; AssetManager2 assetmanager; - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -137,7 +137,7 @@ TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) { desired_config.language[1] = 'e'; AssetManager2 assetmanager; - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -466,10 +466,10 @@ TEST_F(AssetManager2Test, ResolveDeepIdReference) { TEST_F(AssetManager2Test, DensityOverride) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_}); - assetmanager.SetConfigurations({{ + assetmanager.SetConfigurations({{{ .density = ResTable_config::DENSITY_XHIGH, .sdkVersion = 21, - }}); + }}}); auto value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/); ASSERT_TRUE(value.has_value()); @@ -721,7 +721,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) { ResTable_config desired_config; AssetManager2 assetmanager; - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_}); assetmanager.SetResourceResolutionLoggingEnabled(false); @@ -736,7 +736,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) { ResTable_config desired_config; AssetManager2 assetmanager; - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_}); auto result = assetmanager.GetLastResourceResolution(); @@ -751,7 +751,7 @@ TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -774,7 +774,7 @@ TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -796,7 +796,7 @@ TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -817,7 +817,7 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); - assetmanager.SetConfigurations({desired_config}); + assetmanager.SetConfigurations({{desired_config}}); assetmanager.SetApkAssets({overlayable_assets_}); const auto map = assetmanager.GetOverlayableMapForPackage(0x7f); diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp index e3fc0a0a4e68..ec2abb84a5d5 100644 --- a/libs/androidfw/tests/BenchmarkHelpers.cpp +++ b/libs/androidfw/tests/BenchmarkHelpers.cpp @@ -66,7 +66,7 @@ void GetResourceBenchmark(const std::vector<std::string>& paths, const ResTable_ AssetManager2 assetmanager; assetmanager.SetApkAssets(apk_assets); if (config != nullptr) { - assetmanager.SetConfigurations({*config}); + assetmanager.SetConfigurations({{{*config}}}); } while (state.KeepRunning()) { diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp index 181d1411fb91..afcb0c1ad964 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -260,7 +260,7 @@ TEST_F(ThemeTest, ThemeRebase) { ResTable_config night{}; night.uiMode = ResTable_config::UI_MODE_NIGHT_YES; night.version = 8u; - am_night.SetConfigurations({night}); + am_night.SetConfigurations({{night}}); auto theme = am.NewTheme(); { diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig index a1f51687b077..faea6d42b156 100644 --- a/libs/hwui/aconfig/hwui_flags.aconfig +++ b/libs/hwui/aconfig/hwui_flags.aconfig @@ -2,6 +2,13 @@ package: "com.android.graphics.hwui.flags" container: "system" flag { + name: "runtime_color_filters_blenders" + namespace: "core_graphics" + description: "API for AGSL authored runtime color filters and blenders" + bug: "358126864" +} + +flag { name: "clip_shader" is_exported: true namespace: "core_graphics" diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 25c767a88b17..c36eda908d32 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -84,6 +84,7 @@ import android.util.ArrayMap; import android.util.IntArray; import android.util.Log; import android.util.Pair; +import android.util.Slog; import android.view.KeyEvent; import com.android.internal.annotations.GuardedBy; @@ -4283,7 +4284,7 @@ public class AudioManager { final OnAudioFocusChangeListener listener = fri.mRequest.getOnAudioFocusChangeListener(); if (listener != null) { - Log.d(TAG, "dispatching onAudioFocusChange(" + Slog.i(TAG, "dispatching onAudioFocusChange(" + msg.arg1 + ") to " + msg.obj); listener.onAudioFocusChange(msg.arg1); } diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h index 060abfdc1ee5..ffbf0a826b4a 100644 --- a/media/jni/android_media_MediaCodecLinearBlock.h +++ b/media/jni/android_media_MediaCodecLinearBlock.h @@ -62,7 +62,7 @@ struct JMediaCodecLinearBlock { std::shared_ptr<C2Buffer> buffer = C2Buffer::CreateLinearBuffer(block.subBlock(offset, size)); for (const std::shared_ptr<const C2Info> &info : mBuffer->info()) { - std::shared_ptr<C2Param> param = std::move(C2Param::Copy(*info)); + std::shared_ptr<C2Param> param = C2Param::Copy(*info); buffer->setInfo(std::static_pointer_cast<C2Info>(param)); } return buffer; diff --git a/nfc/api/current.txt b/nfc/api/current.txt index b0d1f71e749f..447e980adaee 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -220,11 +220,14 @@ package android.nfc.cardemulation { field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT"; field public static final String CATEGORY_OTHER = "other"; field public static final String CATEGORY_PAYMENT = "payment"; + field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String DH = "DH"; + field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String ESE = "ESE"; field public static final String EXTRA_CATEGORY = "category"; field public static final String EXTRA_SERVICE_COMPONENT = "component"; field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1 field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2 field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0 + field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String UICC = "UICC"; } public abstract class HostApduService extends android.app.Service { diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index 3375e18c001d..2ff9829ddfd7 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -57,6 +57,7 @@ package android.nfc { @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension { method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState(); @@ -74,6 +75,8 @@ package android.nfc.cardemulation { public final class CardEmulation { method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int); + method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, @Nullable String, @Nullable String); + method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity); } } diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index 90ca92f299a4..6c0f93354683 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -88,7 +88,7 @@ interface INfcAdapter boolean isReaderOptionEnabled(); boolean isReaderOptionSupported(); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)") - boolean enableReaderOption(boolean enable); + boolean enableReaderOption(boolean enable, in String pkg); boolean isObserveModeSupported(); boolean isObserveModeEnabled(); boolean setObserveMode(boolean enabled, String pkg); @@ -113,4 +113,5 @@ interface INfcAdapter void clearPreference(); void setScreenState(); void checkFirmware(); + List<String> fetchActiveNfceeList(); } diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index cb97f23e813c..79f1275ec629 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -48,6 +48,6 @@ interface INfcCardEmulation boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status); boolean isDefaultPaymentRegistered(); - boolean overrideRoutingTable(int userHandle, String protocol, String technology); - boolean recoverRoutingTable(int userHandle); + void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg); + void recoverRoutingTable(int userHandle); } diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index b36b705245cd..525e2c58a82c 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -2011,7 +2011,8 @@ public final class NfcAdapter { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } - return callServiceReturn(() -> sService.enableReaderOption(enable), false); + return callServiceReturn(() -> + sService.enableReaderOption(enable, mContext.getPackageName()), false); } diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java index 2ec819cdc1a9..204ba9fbefad 100644 --- a/nfc/java/android/nfc/NfcOemExtension.java +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -26,6 +26,8 @@ import android.os.Binder; import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Executor; /** @@ -153,6 +155,19 @@ public final class NfcOemExtension { NfcAdapter.callService(() -> NfcAdapter.sService.checkFirmware()); } + /** + * Get the Active NFCEE (NFC Execution Environment) List + * + * @return List of activated secure elements on success + * which can contain "eSE" and "UICC", otherwise empty list. + */ + @NonNull + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public List<String> getActiveNfceeList() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sService.fetchActiveNfceeList(), new ArrayList<String>()); + } + private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub { @Override public void onTagConnected(boolean connected, Tag tag) throws RemoteException { diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index e0438ce9258c..0605dbe130d3 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.StringDef; import android.annotation.SystemApi; import android.annotation.UserHandleAware; import android.annotation.UserIdInt; @@ -43,6 +44,8 @@ import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.HexFormat; import java.util.List; @@ -148,6 +151,21 @@ public final class CardEmulation { * that service will be invoked directly. */ public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; + /** + * Route to Device Host (DH). + */ + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public static final String DH = "DH"; + /** + * Route to eSE. + */ + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public static final String ESE = "ESE"; + /** + * Route to UICC. + */ + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public static final String UICC = "UICC"; static boolean sIsInitialized = false; static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>(); @@ -865,11 +883,22 @@ public final class CardEmulation { sService.setServiceEnabledForCategoryOther(userId, service, status), false); } + /** @hide */ + @StringDef({ + DH, + ESE, + UICC + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProtocolAndTechnologyRoute {} + /** * Setting NFC controller routing table, which includes Protocol Route and Technology Route, * while this Activity is in the foreground. * - * The parameter set to null can be used to keep current values for that entry. + * The parameter set to null can be used to keep current values for that entry. Either + * Protocol Route or Technology Route should be override when calling this API, otherwise + * throw {@link IllegalArgumentException}. * <p> * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route: * <pre> @@ -877,26 +906,40 @@ public final class CardEmulation { * mNfcAdapter.overrideRoutingTable(this , "ESE" , null); * }</pre> * </p> - * Also activities must call this method when it goes to the background, - * with all parameters set to null. + * Also activities must call {@link #recoverRoutingTable(Activity)} + * when it goes to the background. Only the package of the + * currently preferred service (the service set as preferred by the current foreground + * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the + * current Default Wallet Role Holder {@link android.app.role.RoleManager#ROLE_WALLET}), + * otherwise a call to this method will fail and throw {@link SecurityException}. * @param activity The Activity that requests NFC controller routing table to be changed. * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE". - * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE". - * @return true if operation is successful and false otherwise - * + * @param technology Tech-A, Tech-B and Tech-F route destination, which can be "DH" or "UICC" + * or "ESE". + * @throws SecurityException if the caller is not the preferred NFC service + * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the + * foreground, or both protocol route and technology route are null. + * <p> * This is a high risk API and only included to support mainline effort * @hide */ - public boolean overrideRoutingTable(Activity activity, String protocol, String technology) { - if (activity == null) { - throw new NullPointerException("activity or service or category is null"); - } + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public void overrideRoutingTable( + @NonNull Activity activity, @ProtocolAndTechnologyRoute @Nullable String protocol, + @ProtocolAndTechnologyRoute @Nullable String technology) { if (!activity.isResumed()) { throw new IllegalArgumentException("Activity must be resumed."); } - return callServiceReturn(() -> + if (protocol == null && technology == null) { + throw new IllegalArgumentException(("Both Protocol and Technology are null.")); + } + callService(() -> sService.overrideRoutingTable( - mContext.getUser().getIdentifier(), protocol, technology), false); + mContext.getUser().getIdentifier(), + protocol, + technology, + mContext.getPackageName())); } /** @@ -904,20 +947,19 @@ public final class CardEmulation { * which was changed by {@link #overrideRoutingTable(Activity, String, String)} * * @param activity The Activity that requested NFC controller routing table to be changed. - * @return true if operation is successful and false otherwise + * @throws IllegalArgumentException if the caller is not in the foreground. * * @hide */ - public boolean recoverRoutingTable(Activity activity) { - if (activity == null) { - throw new NullPointerException("activity is null"); - } + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public void recoverRoutingTable(@NonNull Activity activity) { if (!activity.isResumed()) { throw new IllegalArgumentException("Activity must be resumed."); } - return callServiceReturn(() -> + callService(() -> sService.recoverRoutingTable( - mContext.getUser().getIdentifier()), false); + mContext.getUser().getIdentifier())); } /** diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig index 5819b98dd411..0fda91d2b48e 100644 --- a/nfc/java/android/nfc/flags.aconfig +++ b/nfc/java/android/nfc/flags.aconfig @@ -133,3 +133,11 @@ flag { description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS" bug: "358129872" } + +flag { + name: "nfc_override_recover_routing_table" + is_exported: true + namespace: "nfc" + description: "Enable override and recover routing table" + bug: "329043523" +} diff --git a/packages/PackageInstaller/TEST_MAPPING b/packages/PackageInstaller/TEST_MAPPING index ff836104f799..da6efeead956 100644 --- a/packages/PackageInstaller/TEST_MAPPING +++ b/packages/PackageInstaller/TEST_MAPPING @@ -30,14 +30,47 @@ "name": "CtsIntentSignatureTestCases" }, { - "name": "CtsPackageInstallerCUJTestCases", + "name": "CtsPackageInstallerCUJInstallationTestCases", "options":[ - { - "exclude-annotation":"androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation":"org.junit.Ignore" - } + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUninstallationTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateOwnerShipTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateSelfTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } ] } ] diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java index d33433f3983b..2fb32a7da432 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java @@ -16,10 +16,12 @@ package com.android.packageinstaller; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.app.Activity; import android.app.AlertDialog; +import android.app.BroadcastOptions; import android.app.Dialog; import android.app.DialogFragment; import android.app.PendingIntent; @@ -161,25 +163,31 @@ public class UnarchiveErrorFragment extends DialogFragment implements return; } + // Allow the error handling actvities to start in the background. + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityStartMode( + MODE_BACKGROUND_ACTIVITY_START_ALLOWED); switch (mStatus) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ - null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); + null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0, + options.toBundle()); break; case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: if (mExtraIntent != null) { activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ - null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); + null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0, + options.toBundle()); } else { Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); - startActivity(intent); + startActivity(intent, options.toBundle()); } break; case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", mInstallerPackageName, null); intent.setData(uri); - startActivity(intent); + startActivity(intent, options.toBundle()); break; default: // Do nothing. The rest of the dialogs are purely informational. diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/Android.bp b/packages/SettingsLib/SelectorWithWidgetPreference/Android.bp index 2fe446d24b34..155ee831ae52 100644 --- a/packages/SettingsLib/SelectorWithWidgetPreference/Android.bp +++ b/packages/SettingsLib/SelectorWithWidgetPreference/Android.bp @@ -20,6 +20,7 @@ android_library { static_libs: [ "androidx.preference_preference", "SettingsLibSettingsTheme", + "settingslib_selectorwithwidgetpreference_flags_lib", ], sdk_version: "system_current", @@ -30,3 +31,25 @@ android_library { "com.android.mediaprovider", ], } + +aconfig_declarations { + name: "settingslib_selectorwithwidgetpreference_flags", + package: "com.android.settingslib.widget.selectorwithwidgetpreference.flags", + container: "system", + srcs: [ + "aconfig/selectorwithwidgetpreference.aconfig", + ], +} + +java_aconfig_library { + name: "settingslib_selectorwithwidgetpreference_flags_lib", + aconfig_declarations: "settingslib_selectorwithwidgetpreference_flags", + + min_sdk_version: "30", + sdk_version: "system_current", + apex_available: [ + "//apex_available:platform", + "com.android.permission", + "com.android.mediaprovider", + ], +} diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/aconfig/selectorwithwidgetpreference.aconfig b/packages/SettingsLib/SelectorWithWidgetPreference/aconfig/selectorwithwidgetpreference.aconfig new file mode 100644 index 000000000000..70cda476bff6 --- /dev/null +++ b/packages/SettingsLib/SelectorWithWidgetPreference/aconfig/selectorwithwidgetpreference.aconfig @@ -0,0 +1,13 @@ +package: "com.android.settingslib.widget.selectorwithwidgetpreference.flags" +container: "system" + +flag { + name: "allow_set_title_max_lines" + namespace: "accessibility" + description: "Allow changes to the title max lines so it's not always fixed to 2" + bug: "356726764" + metadata { + purpose: PURPOSE_BUGFIX + } +} + diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml new file mode 100644 index 000000000000..7ffde2578cc1 --- /dev/null +++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <declare-styleable name="SelectorWithWidgetPreference"> + <!-- The maximum number of lines for rendering the title. --> + <attr name="titleMaxLines" format="integer" /> + </declare-styleable> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java index f2ce8a965dfa..34de5c4a5d75 100644 --- a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java +++ b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java @@ -17,15 +17,21 @@ package com.android.settingslib.widget; import android.content.Context; +import android.content.res.TypedArray; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.preference.CheckBoxPreference; import androidx.preference.PreferenceViewHolder; import com.android.settingslib.widget.preference.selector.R; +import com.android.settingslib.widget.selectorwithwidgetpreference.flags.Flags; /** * Selector preference (checkbox or radio button) with an optional additional widget. @@ -41,6 +47,8 @@ import com.android.settingslib.widget.preference.selector.R; * on the right side that can open another page. */ public class SelectorWithWidgetPreference extends CheckBoxPreference { + @VisibleForTesting + static final int DEFAULT_MAX_LINES = 2; /** * Interface definition for a callback to be invoked when the preference is clicked. @@ -63,6 +71,8 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { private boolean mIsCheckBox = false; // whether to display this button as a checkbox private View.OnClickListener mExtraWidgetOnClickListener; + private int mTitleMaxLines; + /** * Perform inflation from XML and apply a class-specific base style. @@ -74,9 +84,10 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { * resource that supplies default values for the view. Can be 0 to not * look for defaults. */ - public SelectorWithWidgetPreference(Context context, AttributeSet attrs, int defStyle) { + public SelectorWithWidgetPreference(@NonNull Context context, @Nullable AttributeSet attrs, + int defStyle) { super(context, attrs, defStyle); - init(); + init(context, attrs, defStyle, /* defStyleRes= */ 0); } /** @@ -88,7 +99,7 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { */ public SelectorWithWidgetPreference(Context context, AttributeSet attrs) { super(context, attrs); - init(); + init(context, attrs, /* defStyleAttr= */ 0, /* defStyleRes= */ 0); } /** @@ -100,7 +111,7 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { public SelectorWithWidgetPreference(Context context, boolean isCheckbox) { super(context, null); mIsCheckBox = isCheckbox; - init(); + init(context, /* attrs= */ null, /* defStyleAttr= */ 0, /* defStyleRes= */ 0); } /** @@ -161,6 +172,11 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { mExtraWidgetContainer = holder.findViewById(R.id.selector_extra_widget_container); setExtraWidgetOnClickListener(mExtraWidgetOnClickListener); + + if (Flags.allowSetTitleMaxLines()) { + TextView title = (TextView) holder.findViewById(android.R.id.title); + title.setMaxLines(mTitleMaxLines); + } } /** @@ -200,7 +216,8 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { return mIsCheckBox; } - private void init() { + private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, + int defStyleRes) { if (mIsCheckBox) { setWidgetLayoutResource(R.layout.preference_widget_checkbox); } else { @@ -208,5 +225,16 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { } setLayoutResource(R.layout.preference_selector_with_widget); setIconSpaceReserved(false); + + if (Flags.allowSetTitleMaxLines()) { + final TypedArray a = + context.obtainStyledAttributes( + attrs, R.styleable.SelectorWithWidgetPreference, defStyleAttr, + defStyleRes); + mTitleMaxLines = + a.getInt(R.styleable.SelectorWithWidgetPreference_titleMaxLines, + DEFAULT_MAX_LINES); + a.recycle(); + } } } diff --git a/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_preference.xml b/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_preference.xml index 4c75344bbde3..526ce1479c68 100644 --- a/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_preference.xml +++ b/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_preference.xml @@ -19,8 +19,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?android:attr/listPreferredItemHeight" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp"> + android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" + android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"> <Spinner android:id="@+id/spinner" diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts index f36344aa4846..a543450821b8 100644 --- a/packages/SettingsLib/Spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/build.gradle.kts @@ -29,7 +29,7 @@ val androidTop: String = File(rootDir, "../../../../..").canonicalPath allprojects { extra["androidTop"] = androidTop - extra["jetpackComposeVersion"] = "1.7.0-beta05" + extra["jetpackComposeVersion"] = "1.7.0-beta07" } subprojects { @@ -37,7 +37,7 @@ subprojects { plugins.withType<AndroidBasePlugin> { configure<BaseExtension> { - compileSdkVersion(34) + compileSdkVersion(35) defaultConfig { minSdk = 21 diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml index 1cca73af9a42..3507605c5ad2 100644 --- a/packages/SettingsLib/Spa/gradle/libs.versions.toml +++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml @@ -15,7 +15,7 @@ # [versions] -agp = "8.5.1" +agp = "8.5.2" compose-compiler = "1.5.11" dexmaker-mockito = "2.28.3" jvm = "17" diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts index ce3d96e2d388..e9153e3e6010 100644 --- a/packages/SettingsLib/Spa/spa/build.gradle.kts +++ b/packages/SettingsLib/Spa/spa/build.gradle.kts @@ -54,13 +54,13 @@ android { dependencies { api(project(":SettingsLibColor")) api("androidx.appcompat:appcompat:1.7.0") - api("androidx.compose.material3:material3:1.3.0-beta04") + api("androidx.compose.material3:material3:1.3.0-beta05") api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion") api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion") api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion") api("androidx.lifecycle:lifecycle-livedata-ktx") api("androidx.lifecycle:lifecycle-runtime-compose") - api("androidx.navigation:navigation-compose:2.8.0-beta05") + api("androidx.navigation:navigation-compose:2.8.0-beta07") api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha") api("com.google.android.material:material:1.11.0") debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion") diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig index 0d124e80dfcf..2b3862f88c07 100644 --- a/packages/SettingsLib/aconfig/settingslib.aconfig +++ b/packages/SettingsLib/aconfig/settingslib.aconfig @@ -119,3 +119,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "audio_sharing_hysteresis_mode_fix" + namespace: "cross_device_experiences" + description: "Gates whether to enable fix for hysteresis mode" + bug: "355222285" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java index de60fdc2b47e..b3ac54a9f7bc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java @@ -21,6 +21,8 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.net.Uri; import android.provider.DeviceConfig; @@ -41,9 +43,12 @@ import com.android.settingslib.flags.Flags; import com.android.settingslib.widget.AdaptiveIcon; import com.android.settingslib.widget.AdaptiveOutlineDrawable; +import com.google.common.collect.ImmutableSet; + import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -57,6 +62,9 @@ public class BluetoothUtils { public static final String BT_ADVANCED_HEADER_ENABLED = "bt_advanced_header_enabled"; private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25; private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH"; + private static final Set<Integer> SA_PROFILES = + ImmutableSet.of( + BluetoothProfile.A2DP, BluetoothProfile.LE_AUDIO, BluetoothProfile.HEARING_AID); private static ErrorListener sErrorListener; @@ -895,4 +903,62 @@ public class BluetoothUtils { } return null; } + + /** + * Gets {@link AudioDeviceAttributes} of bluetooth device for spatial audio. Returns null if + * it's not an audio device(no A2DP, LE Audio and Hearing Aid profile). + */ + @Nullable + public static AudioDeviceAttributes getAudioDeviceAttributesForSpatialAudio( + CachedBluetoothDevice cachedDevice, + @AudioManager.AudioDeviceCategory int audioDeviceCategory) { + AudioDeviceAttributes saDevice = null; + for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) { + // pick first enabled profile that is compatible with spatial audio + if (SA_PROFILES.contains(profile.getProfileId()) + && profile.isEnabled(cachedDevice.getDevice())) { + switch (profile.getProfileId()) { + case BluetoothProfile.A2DP: + saDevice = + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + cachedDevice.getAddress()); + break; + case BluetoothProfile.LE_AUDIO: + if (audioDeviceCategory + == AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER) { + saDevice = + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_SPEAKER, + cachedDevice.getAddress()); + } else { + saDevice = + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_HEADSET, + cachedDevice.getAddress()); + } + + break; + case BluetoothProfile.HEARING_AID: + saDevice = + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_HEARING_AID, + cachedDevice.getAddress()); + break; + default: + Log.i( + TAG, + "unrecognized profile for spatial audio: " + + profile.getProfileId()); + break; + } + break; + } + } + return saDevice; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingId.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingId.java index 20a0339b9182..58dc8c7aad6c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingId.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingId.java @@ -108,6 +108,12 @@ public @interface DeviceSettingId { /** Device setting ID for device details footer. */ int DEVICE_SETTING_ID_DEVICE_DETAILS_FOOTER = 19; + /** Device setting ID for spatial audio group. */ + int DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE = 20; + + /** Device setting ID for "More Settings" page. */ + int DEVICE_SETTING_ID_MORE_SETTINGS = 21; + /** Device setting ID for ANC. */ int DEVICE_SETTING_ID_ANC = 1001; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingItem.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingItem.kt index 9ee33b0dbffe..a0fe5d275b36 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingItem.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingItem.kt @@ -27,6 +27,7 @@ import android.os.Parcelable * @property packageName The package name for service binding. * @property className The class name for service binding. * @property intentAction The intent action for service binding. + * @property preferenceKey The preference key if it's a built-in preference. * @property extras Extra bundle */ data class DeviceSettingItem( @@ -34,6 +35,7 @@ data class DeviceSettingItem( val packageName: String, val className: String, val intentAction: String, + val preferenceKey: String? = null, val extras: Bundle = Bundle.EMPTY, ) : Parcelable { @@ -45,6 +47,7 @@ data class DeviceSettingItem( writeString(packageName) writeString(className) writeString(intentAction) + writeString(preferenceKey) writeBundle(extras) } } @@ -60,6 +63,7 @@ data class DeviceSettingItem( packageName = readString() ?: "", className = readString() ?: "", intentAction = readString() ?: "", + preferenceKey = readString() ?: "", extras = readBundle((Bundle::class.java.classLoader)) ?: Bundle.EMPTY, ) } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt index 326bb31bdb9f..ce7064c9d781 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt @@ -18,6 +18,7 @@ package com.android.settingslib.bluetooth.devicesettings.data.repository import android.bluetooth.BluetoothAdapter import android.content.Context +import android.text.TextUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference import com.android.settingslib.bluetooth.devicesettings.DeviceSetting @@ -28,6 +29,7 @@ import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference import com.android.settingslib.bluetooth.devicesettings.ToggleInfo import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel +import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel @@ -76,8 +78,7 @@ class DeviceSettingRepositoryImpl( coroutineScope, backgroundCoroutineContext, ) - } - ) + }) override suspend fun getDeviceSettingsConfig( cachedDevice: CachedBluetoothDevice @@ -96,11 +97,15 @@ class DeviceSettingRepositoryImpl( DeviceSettingConfigModel( mainItems = mainContentItems.map { it.toModel() }, moreSettingsItems = moreSettingsItems.map { it.toModel() }, - moreSettingsPageFooter = moreSettingsFooter - ) + moreSettingsPageFooter = moreSettingsFooter) - private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel = - DeviceSettingConfigItemModel(settingId) + private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel { + return if (!TextUtils.isEmpty(preferenceKey)) { + DeviceSettingConfigItemModel.BuiltinItem(settingId, preferenceKey!!) + } else { + DeviceSettingConfigItemModel.AppProvidedItem(settingId) + } + } private fun DeviceSetting.toModel( cachedDevice: CachedBluetoothDevice, @@ -113,7 +118,7 @@ class DeviceSettingRepositoryImpl( id = settingId, title = pref.title, summary = pref.summary, - icon = pref.icon, + icon = pref.icon?.let { DeviceSettingIcon.BitmapIcon(it) }, isAllowedChangingState = pref.isAllowedChangingState, intent = pref.intent, switchState = @@ -149,5 +154,6 @@ class DeviceSettingRepositoryImpl( else -> DeviceSettingModel.Unknown(cachedDevice, settingId) } - private fun ToggleInfo.toModel(): ToggleModel = ToggleModel(label, icon) + private fun ToggleInfo.toModel(): ToggleModel = + ToggleModel(label, DeviceSettingIcon.BitmapIcon(icon)) } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt index cd597ee65bce..e97f76cca3a9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt @@ -25,9 +25,20 @@ data class DeviceSettingConfigModel( /** Items need to be shown in device details more settings page. */ val moreSettingsItems: List<DeviceSettingConfigItemModel>, /** Footer text in more settings page. */ - val moreSettingsPageFooter: String) + val moreSettingsPageFooter: String +) /** Models a device setting item in config. */ -data class DeviceSettingConfigItemModel( - @DeviceSettingId val settingId: Int, -) +sealed interface DeviceSettingConfigItemModel { + @DeviceSettingId val settingId: Int + + /** A built-in item in Settings. */ + data class BuiltinItem( + @DeviceSettingId override val settingId: Int, + val preferenceKey: String? + ) : DeviceSettingConfigItemModel + + /** A remote item provided by other apps. */ + data class AppProvidedItem(@DeviceSettingId override val settingId: Int) : + DeviceSettingConfigItemModel +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt index db782803937c..2a6321704a1a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt @@ -18,6 +18,7 @@ package com.android.settingslib.bluetooth.devicesettings.shared.model import android.content.Intent import android.graphics.Bitmap +import androidx.annotation.DrawableRes import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId @@ -32,7 +33,7 @@ sealed interface DeviceSettingModel { @DeviceSettingId override val id: Int, val title: String, val summary: String? = null, - val icon: Bitmap? = null, + val icon: DeviceSettingIcon? = null, val intent: Intent? = null, val switchState: DeviceSettingStateModel.ActionSwitchPreferenceState? = null, val isAllowedChangingState: Boolean = true, @@ -59,4 +60,12 @@ sealed interface DeviceSettingModel { } /** Models a toggle in [DeviceSettingModel.MultiTogglePreference]. */ -data class ToggleModel(val label: String, val icon: Bitmap) +data class ToggleModel(val label: String, val icon: DeviceSettingIcon) + +/** Models an icon in device settings. */ +sealed interface DeviceSettingIcon { + + data class BitmapIcon(val bitmap: Bitmap) : DeviceSettingIcon + + data class ResourceIcon(@DrawableRes val resId: Int) : DeviceSettingIcon +} diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java index 2f4b2efeec7f..0d4ce5be7b0e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java @@ -22,6 +22,7 @@ import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent; import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime; +import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId; import static android.service.notification.ZenModeConfig.tryParseEventConditionId; import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId; @@ -52,9 +53,11 @@ import androidx.annotation.Nullable; import com.android.settingslib.R; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import java.util.Comparator; import java.util.Objects; /** @@ -87,6 +90,33 @@ public class ZenMode implements Parcelable { .allowPriorityChannels(false) .build(); + private static final Comparator<Integer> PRIORITIZED_TYPE_COMPARATOR = new Comparator<>() { + + private static final ImmutableList</* @AutomaticZenRule.Type */ Integer> + PRIORITIZED_TYPES = ImmutableList.of( + AutomaticZenRule.TYPE_BEDTIME, + AutomaticZenRule.TYPE_DRIVING); + + @Override + public int compare(Integer first, Integer second) { + if (PRIORITIZED_TYPES.contains(first) && PRIORITIZED_TYPES.contains(second)) { + return PRIORITIZED_TYPES.indexOf(first) - PRIORITIZED_TYPES.indexOf(second); + } else if (PRIORITIZED_TYPES.contains(first)) { + return -1; + } else if (PRIORITIZED_TYPES.contains(second)) { + return 1; + } else { + return 0; + } + } + }; + + // Manual DND first, Bedtime/Driving, then alphabetically. + static final Comparator<ZenMode> PRIORITIZING_COMPARATOR = Comparator + .comparing(ZenMode::isManualDnd).reversed() + .thenComparing(ZenMode::getType, PRIORITIZED_TYPE_COMPARATOR) + .thenComparing(ZenMode::getName); + public enum Status { ENABLED, ENABLED_AND_ACTIVE, @@ -129,7 +159,11 @@ public class ZenMode implements Parcelable { } public static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) { - return new ZenMode(MANUAL_DND_MODE_ID, manualRule, + // Manual rule is owned by the system, so we set it here + AutomaticZenRule manualRuleWithPkg = new AutomaticZenRule.Builder(manualRule) + .setPackage(PACKAGE_ANDROID) + .build(); + return new ZenMode(MANUAL_DND_MODE_ID, manualRuleWithPkg, isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED, true); } @@ -220,6 +254,16 @@ public class ZenMode implements Parcelable { return getTriggerDescription(); } + /** + * Returns an icon "key" that is guaranteed to be different if the icon is different. Note that + * the inverse is not true, i.e. two keys can be different and the icon still be visually the + * same. + */ + @NonNull + public String getIconKey() { + return mRule.getType() + ":" + mRule.getPackageName() + ":" + mRule.getIconResId(); + } + @NonNull public ListenableFuture<Drawable> getIcon(@NonNull Context context, @NonNull ZenIconLoader iconLoader) { diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java index 64e503b323b8..c8a12f481c6e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java @@ -34,7 +34,6 @@ import com.android.settingslib.R; import java.time.Duration; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.Map; @@ -92,10 +91,7 @@ public class ZenModesBackend { } } - // Manual DND first, then alphabetically. - modes.sort(Comparator.comparing(ZenMode::isManualDnd).reversed() - .thenComparing(ZenMode::getName)); - + modes.sort(ZenMode.PRIORITIZING_COMPARATOR); return modes; } diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt index ebba7f152b90..2f8105ae461d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt @@ -63,7 +63,7 @@ typealias GroupIdToVolumes = Map<Int, Int> /** Provides audio sharing functionality. */ interface AudioSharingRepository { /** Whether the device is in audio sharing. */ - val inAudioSharing: Flow<Boolean> + val inAudioSharing: StateFlow<Boolean> /** The primary headset groupId in audio sharing. */ val primaryGroupId: StateFlow<Int> @@ -101,7 +101,7 @@ class AudioSharingRepositoryImpl( .flowOn(backgroundCoroutineContext) .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false) - override val inAudioSharing: Flow<Boolean> = + override val inAudioSharing: StateFlow<Boolean> = isAudioSharingProfilesReady.flatMapLatest { ready -> if (ready) { btManager.profileManager.leAudioBroadcastProfile.onBroadcastStartedOrStopped @@ -113,6 +113,7 @@ class AudioSharingRepositoryImpl( flowOf(false) } } + .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false) private val primaryChange: Flow<Unit> = callbackFlow { val callback = @@ -254,7 +255,7 @@ class AudioSharingRepositoryImpl( } class AudioSharingRepositoryEmptyImpl : AudioSharingRepository { - override val inAudioSharing: Flow<Boolean> = flowOf(false) + override val inAudioSharing: StateFlow<Boolean> = MutableStateFlow(false) override val primaryGroupId: StateFlow<Int> = MutableStateFlow(BluetoothCsipSetCoordinator.GROUP_ID_INVALID) override val secondaryGroupId: StateFlow<Int> = diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp index 75c40bfa8b60..f380e7f7e7a6 100644 --- a/packages/SettingsLib/tests/robotests/Android.bp +++ b/packages/SettingsLib/tests/robotests/Android.bp @@ -56,6 +56,7 @@ android_robolectric_test { "flag-junit", "settingslib_media_flags_lib", "settingslib_illustrationpreference_flags_lib", + "settingslib_selectorwithwidgetpreference_flags_lib", "testng", // TODO: remove once JUnit on Android provides assertThrows ], java_resource_dirs: ["config"], diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java index 4551f1eba84b..926d3cb448e8 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java @@ -31,10 +31,13 @@ import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastReceiveState; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.net.Uri; import android.platform.test.flag.junit.SetFlagsRule; @@ -70,6 +73,9 @@ public class BluetoothUtilsTest { @Mock private BluetoothDevice mBluetoothDevice; @Mock private AudioManager mAudioManager; @Mock private PackageManager mPackageManager; + @Mock private LeAudioProfile mA2dpProfile; + @Mock private LeAudioProfile mLeAudioProfile; + @Mock private LeAudioProfile mHearingAid; @Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothProfileManager mProfileManager; @Mock private LocalBluetoothManager mLocalBluetoothManager; @@ -100,6 +106,9 @@ public class BluetoothUtilsTest { when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager); when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); + when(mA2dpProfile.getProfileId()).thenReturn(BluetoothProfile.A2DP); + when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO); + when(mHearingAid.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID); } @Test @@ -756,4 +765,84 @@ public class BluetoothUtilsTest { mContext.getContentResolver(), mLocalBluetoothManager)) .isEqualTo(mCachedBluetoothDevice); } + + @Test + public void getAudioDeviceAttributesForSpatialAudio_bleHeadset() { + String address = "11:22:33:44:55:66"; + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mCachedBluetoothDevice.getAddress()).thenReturn(address); + when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile)); + when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true); + + AudioDeviceAttributes attr = + BluetoothUtils.getAudioDeviceAttributesForSpatialAudio( + mCachedBluetoothDevice, AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES); + + assertThat(attr) + .isEqualTo( + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_HEADSET, + address)); + } + + @Test + public void getAudioDeviceAttributesForSpatialAudio_bleSpeaker() { + String address = "11:22:33:44:55:66"; + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mCachedBluetoothDevice.getAddress()).thenReturn(address); + when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile)); + when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true); + + AudioDeviceAttributes attr = + BluetoothUtils.getAudioDeviceAttributesForSpatialAudio( + mCachedBluetoothDevice, AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER); + + assertThat(attr) + .isEqualTo( + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_SPEAKER, + address)); + } + + @Test + public void getAudioDeviceAttributesForSpatialAudio_a2dp() { + String address = "11:22:33:44:55:66"; + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mCachedBluetoothDevice.getAddress()).thenReturn(address); + when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mA2dpProfile)); + when(mA2dpProfile.isEnabled(mBluetoothDevice)).thenReturn(true); + + AudioDeviceAttributes attr = + BluetoothUtils.getAudioDeviceAttributesForSpatialAudio( + mCachedBluetoothDevice, AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES); + + assertThat(attr) + .isEqualTo( + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + address)); + } + + @Test + public void getAudioDeviceAttributesForSpatialAudio_hearingAid() { + String address = "11:22:33:44:55:66"; + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mCachedBluetoothDevice.getAddress()).thenReturn(address); + when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mHearingAid)); + when(mHearingAid.isEnabled(mBluetoothDevice)).thenReturn(true); + + AudioDeviceAttributes attr = + BluetoothUtils.getAudioDeviceAttributesForSpatialAudio( + mCachedBluetoothDevice, AudioManager.AUDIO_DEVICE_CATEGORY_HEARING_AID); + + assertThat(attr) + .isEqualTo( + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_HEARING_AID, + address)); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt index 2b29a6ef5e5a..9568d66ac7db 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt @@ -37,9 +37,9 @@ class DeviceSettingsConfigTest { "package_name_1", "class_name_1", "intent_action_1", - Bundle() - ) - ), + null, + Bundle(), + )), moreSettingsItems = listOf( DeviceSettingItem( @@ -47,9 +47,9 @@ class DeviceSettingsConfigTest { "package_name_2", "class_name_2", "intent_action_2", - Bundle() - ) - ), + null, + Bundle(), + )), moreSettingsFooter = "footer", extras = Bundle().apply { putString("key1", "value1") }, ) diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt index fee23945f7b5..4c5ee9e4ee4c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt @@ -40,6 +40,7 @@ import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreferenceSta import com.android.settingslib.bluetooth.devicesettings.ToggleInfo import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel +import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel @@ -352,7 +353,7 @@ class DeviceSettingRepositoryTest { val pref = serviceResponse.preference as ActionSwitchPreference assertThat(actual.title).isEqualTo(pref.title) assertThat(actual.summary).isEqualTo(pref.summary) - assertThat(actual.icon).isEqualTo(pref.icon) + assertThat(actual.icon).isEqualTo(DeviceSettingIcon.BitmapIcon(pref.icon!!)) assertThat(actual.isAllowedChangingState).isEqualTo(pref.isAllowedChangingState) if (pref.hasSwitch()) { assertThat(actual.switchState!!.checked).isEqualTo(pref.checked) diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java index d9fdcc38b576..bab4bc3b0bf5 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java @@ -16,9 +16,16 @@ package com.android.settingslib.notification.modes; +import static android.app.AutomaticZenRule.TYPE_BEDTIME; +import static android.app.AutomaticZenRule.TYPE_DRIVING; +import static android.app.AutomaticZenRule.TYPE_IMMERSIVE; +import static android.app.AutomaticZenRule.TYPE_OTHER; +import static android.app.AutomaticZenRule.TYPE_THEATER; +import static android.app.AutomaticZenRule.TYPE_UNKNOWN; import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; +import static android.service.notification.SystemZenRules.PACKAGE_ANDROID; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -37,6 +44,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; +import java.util.ArrayList; +import java.util.List; + @RunWith(RobolectricTestRunner.class) public class ZenModeTest { @@ -45,7 +55,7 @@ public class ZenModeTest { private static final AutomaticZenRule ZEN_RULE = new AutomaticZenRule.Builder("Driving", Uri.parse("drive")) .setPackage("com.some.driving.thing") - .setType(AutomaticZenRule.TYPE_DRIVING) + .setType(TYPE_DRIVING) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(ZEN_POLICY) .build(); @@ -67,6 +77,7 @@ public class ZenModeTest { assertThat(manualMode.canEditNameAndIcon()).isFalse(); assertThat(manualMode.canBeDeleted()).isFalse(); assertThat(manualMode.isActive()).isFalse(); + assertThat(manualMode.getRule().getPackageName()).isEqualTo(PACKAGE_ANDROID); } @Test @@ -224,6 +235,28 @@ public class ZenModeTest { } @Test + public void comparator_prioritizes() { + ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE; + ZenMode driving1 = new TestModeBuilder().setName("b1").setType(TYPE_DRIVING).build(); + ZenMode driving2 = new TestModeBuilder().setName("b2").setType(TYPE_DRIVING).build(); + ZenMode bedtime1 = new TestModeBuilder().setName("c1").setType(TYPE_BEDTIME).build(); + ZenMode bedtime2 = new TestModeBuilder().setName("c2").setType(TYPE_BEDTIME).build(); + ZenMode other = new TestModeBuilder().setName("a1").setType(TYPE_OTHER).build(); + ZenMode immersive = new TestModeBuilder().setName("a2").setType(TYPE_IMMERSIVE).build(); + ZenMode unknown = new TestModeBuilder().setName("a3").setType(TYPE_UNKNOWN).build(); + ZenMode theater = new TestModeBuilder().setName("a4").setType(TYPE_THEATER).build(); + + ArrayList<ZenMode> list = new ArrayList<>(List.of(other, theater, bedtime1, unknown, + driving2, manualDnd, driving1, bedtime2, immersive)); + list.sort(ZenMode.PRIORITIZING_COMPARATOR); + + assertThat(list) + .containsExactly(manualDnd, bedtime1, bedtime2, driving1, driving2, other, + immersive, unknown, theater) + .inOrder(); + } + + @Test public void writeToParcel_equals() { assertUnparceledIsEqualToOriginal("example", new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, false))); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java index 60885f1079d3..243ce85bd579 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java @@ -23,22 +23,31 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.Application; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.widget.TextView; import androidx.preference.PreferenceViewHolder; +import androidx.test.core.app.ApplicationProvider; import com.android.settingslib.widget.preference.selector.R; +import com.android.settingslib.widget.selectorwithwidgetpreference.flags.Flags; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class SelectorWithWidgetPreferenceTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Application mContext; private SelectorWithWidgetPreference mPreference; @@ -55,7 +64,7 @@ public class SelectorWithWidgetPreferenceTest { @Before public void setUp() { - mContext = RuntimeEnvironment.application; + mContext = ApplicationProvider.getApplicationContext(); mPreference = new SelectorWithWidgetPreference(mContext); View view = LayoutInflater.from(mContext) @@ -121,6 +130,60 @@ public class SelectorWithWidgetPreferenceTest { } @Test + @DisableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES) + public void onBindViewHolder_titleMaxLinesSet_flagOff_titleMaxLinesMatchesDefault() { + final int titleMaxLines = 5; + AttributeSet attributeSet = Robolectric.buildAttributeSet() + .addAttribute(R.attr.titleMaxLines, String.valueOf(titleMaxLines)) + .build(); + mPreference = new SelectorWithWidgetPreference(mContext, attributeSet); + View view = LayoutInflater.from(mContext) + .inflate(mPreference.getLayoutResource(), null /* root */); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + + mPreference.onBindViewHolder(preferenceViewHolder); + + TextView title = (TextView) preferenceViewHolder.findViewById(android.R.id.title); + assertThat(title.getMaxLines()).isEqualTo(SelectorWithWidgetPreference.DEFAULT_MAX_LINES); + } + + @Test + @EnableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES) + public void onBindViewHolder_noTitleMaxLinesSet_titleMaxLinesMatchesDefault() { + AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); + mPreference = new SelectorWithWidgetPreference(mContext, attributeSet); + View view = LayoutInflater.from(mContext) + .inflate(mPreference.getLayoutResource(), null /* root */); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + + mPreference.onBindViewHolder(preferenceViewHolder); + + TextView title = (TextView) preferenceViewHolder.findViewById(android.R.id.title); + assertThat(title.getMaxLines()).isEqualTo(SelectorWithWidgetPreference.DEFAULT_MAX_LINES); + } + + @Test + @EnableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES) + public void onBindViewHolder_titleMaxLinesSet_titleMaxLinesUpdated() { + final int titleMaxLines = 5; + AttributeSet attributeSet = Robolectric.buildAttributeSet() + .addAttribute(R.attr.titleMaxLines, String.valueOf(titleMaxLines)) + .build(); + mPreference = new SelectorWithWidgetPreference(mContext, attributeSet); + View view = LayoutInflater.from(mContext) + .inflate(mPreference.getLayoutResource(), null /* root */); + PreferenceViewHolder preferenceViewHolder = + PreferenceViewHolder.createInstanceForTests(view); + + mPreference.onBindViewHolder(preferenceViewHolder); + + TextView title = (TextView) preferenceViewHolder.findViewById(android.R.id.title); + assertThat(title.getMaxLines()).isEqualTo(titleMaxLines); + } + + @Test public void nullSummary_containerShouldBeGone() { mPreference.setSummary(null); View summaryContainer = new View(mContext); diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp index 75f8384321b0..3e62b7b2cf6e 100644 --- a/packages/SettingsProvider/Android.bp +++ b/packages/SettingsProvider/Android.bp @@ -32,6 +32,7 @@ android_library { "unsupportedappusage", ], static_libs: [ + "aconfig_device_paths_java", "aconfig_new_storage_flags_lib", "aconfigd_java_utils", "aconfig_demo_flags_java_lib", diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java index 8b0772bb644d..121bd3e6e771 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java @@ -20,8 +20,10 @@ import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT; -import android.aconfig.Aconfig.parsed_flag; -import android.aconfig.Aconfig.parsed_flags; +import android.aconfig.DeviceProtos; +import android.aconfig.nano.Aconfig; +import android.aconfig.nano.Aconfig.parsed_flag; +import android.aconfig.nano.Aconfig.parsed_flags; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.AttributionSource; @@ -42,7 +44,6 @@ import android.provider.Settings.Config.SyncDisabledMode; import android.provider.UpdatableDeviceConfigServiceReadiness; import android.util.Slog; -import com.android.internal.pm.pkg.component.AconfigFlags; import com.android.internal.util.FastPrintWriter; import java.io.File; @@ -136,11 +137,8 @@ public final class DeviceConfigService extends Binder { continue; } - for (parsed_flag flag : parsedFlags.getParsedFlagList()) { - String namespace = flag.getNamespace(); - String packageName = flag.getPackage(); - String name = flag.getName(); - nameSet.add(namespace + "/" + packageName + "." + name); + for (parsed_flag flag : parsedFlags.parsedFlag) { + nameSet.add(flag.namespace + "/" + flag.package_ + "." + flag.name); } } } catch (IOException e) { @@ -169,6 +167,7 @@ public final class DeviceConfigService extends Binder { static final class MyShellCommand extends ShellCommand { final SettingsProvider mProvider; + private HashMap<String, parsed_flag> mAconfigParsedFlags; enum CommandVerb { GET, @@ -186,6 +185,51 @@ public final class DeviceConfigService extends Binder { MyShellCommand(SettingsProvider provider) { mProvider = provider; + + if (Flags.checkRootAndReadOnly()) { + List<parsed_flag> parsedFlags; + try { + parsedFlags = DeviceProtos.loadAndParseFlagProtos(); + } catch (IOException e) { + throw new IllegalStateException("failed to parse aconfig protos"); + } + + mAconfigParsedFlags = new HashMap(); + for (parsed_flag flag : parsedFlags) { + mAconfigParsedFlags.put(flag.package_ + "." + flag.name, flag); + } + } + } + + /** + * Return true if a flag is aconfig. + */ + private boolean isAconfigFlag(String name) { + return mAconfigParsedFlags.get(name) != null; + } + + /** + * Return true if a flag is both aconfig and read-only. + * + * @return true if a flag is both aconfig and read-only + */ + private boolean isReadOnly(String name) { + parsed_flag flag = mAconfigParsedFlags.get(name); + if (flag != null) { + if (flag.permission == Aconfig.READ_ONLY) { + return true; + } + } + return false; + } + + /** + * Return true if the calling process is root. + * + * @return true if a flag is aconfig, and the calling process is root + */ + private boolean isRoot() { + return Binder.getCallingUid() == Process.ROOT_UID; } public static HashMap<String, String> getAllFlags(IContentProvider provider) { @@ -414,21 +458,71 @@ public final class DeviceConfigService extends Binder { pout.println(DeviceConfig.getProperty(namespace, key)); break; case PUT: + if (Flags.checkRootAndReadOnly()) { + if (isAconfigFlag(key)) { + if (!isRoot()) { + pout.println("Error: must be root to write aconfig flag"); + break; + } + + if (isReadOnly(key)) { + pout.println("Error: cannot write read-only flag"); + break; + } + } + } + DeviceConfig.setProperty(namespace, key, value, makeDefault); break; case OVERRIDE: - AconfigFlags.Permission permission = - (new AconfigFlags()).getFlagPermission(key); - if (permission == AconfigFlags.Permission.READ_ONLY) { - pout.println("cannot override read-only flag " + key); - } else { - DeviceConfig.setLocalOverride(namespace, key, value); + if (Flags.checkRootAndReadOnly()) { + if (isAconfigFlag(key)) { + if (!isRoot()) { + pout.println("Error: must be root to write aconfig flag"); + break; + } + + if (isReadOnly(key)) { + pout.println("Error: cannot write read-only flag"); + break; + } + } } + + DeviceConfig.setLocalOverride(namespace, key, value); break; case CLEAR_OVERRIDE: + if (Flags.checkRootAndReadOnly()) { + if (isAconfigFlag(key)) { + if (!isRoot()) { + pout.println("Error: must be root to write aconfig flag"); + break; + } + + if (isReadOnly(key)) { + pout.println("Error: cannot write read-only flag"); + break; + } + } + } + DeviceConfig.clearLocalOverride(namespace, key); break; case DELETE: + if (Flags.checkRootAndReadOnly()) { + if (isAconfigFlag(key)) { + if (!isRoot()) { + pout.println("Error: must be root to write aconfig flag"); + break; + } + + if (isReadOnly(key)) { + pout.println("Error: cannot write read-only flag"); + break; + } + } + } + pout.println(delete(iprovider, namespace, key) ? "Successfully deleted " + key + " from " + namespace : "Failed to delete " + key + " from " + namespace); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig index b1e6d6650226..006e644b2ac7 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig +++ b/packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig @@ -70,3 +70,14 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "check_root_and_read_only" + namespace: "core_experiments_team_internal" + description: "Check root and aconfig flag permissions in adb shell device_config commands." + bug: "342636474" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 6d78705d1fbc..3aa89eec54ff 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -748,6 +748,7 @@ android_library { "//frameworks/libs/systemui:motion_tool_lib", "//frameworks/libs/systemui:contextualeducationlib", "androidx.core_core-animation-testing", + "androidx.lifecycle_lifecycle-runtime-testing", "androidx.compose.ui_ui", "flag-junit", "ravenwood-junit", @@ -789,6 +790,7 @@ android_library { "SystemUI-tests-base", "androidx.test.uiautomator_uiautomator", "androidx.core_core-animation-testing", + "androidx.lifecycle_lifecycle-runtime-testing", "mockito-target-extended-minus-junit4", "mockito-kotlin-nodeps", "androidx.test.ext.junit", @@ -836,14 +838,6 @@ android_app { ], manifest: "tests/AndroidManifest-base.xml", - srcs: [ - "src/**/*.kt", - "src/**/*.java", - "src/**/I*.aidl", - ":ReleaseJavaFiles", - "compose/features/src/**/*.kt", - "compose/facade/enabled/src/**/*.kt", - ], static_libs: [ "//frameworks/libs/systemui:compilelib", "SystemUI-tests-base", diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 1d9f46971502..398c915b02b3 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -480,6 +480,7 @@ <activity android:name=".touchpad.tutorial.ui.view.TouchpadTutorialActivity" android:exported="true" + android:screenOrientation="userLandscape" android:theme="@style/Theme.AppCompat.NoActionBar"> <intent-filter> <action android:name="com.android.systemui.action.TOUCHPAD_TUTORIAL"/> @@ -489,6 +490,7 @@ <activity android:name=".inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity" android:exported="true" + android:screenOrientation="userLandscape" android:theme="@style/Theme.AppCompat.NoActionBar"> <intent-filter> <action android:name="com.android.systemui.action.TOUCHPAD_KEYBOARD_TUTORIAL"/> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp index c881e07e554e..c60eb61c57eb 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp +++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp @@ -36,7 +36,7 @@ android_app { "androidx.coordinatorlayout_coordinatorlayout", "androidx.core_core", "androidx.preference_preference", - "androidx.viewpager_viewpager", + "androidx.viewpager2_viewpager2", "com_android_systemui_flags_lib", "SettingsLibDisplayUtils", "SettingsLibSettingsTheme", diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml index 462c90bcabf3..e1b6e6325851 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml @@ -22,7 +22,7 @@ android:orientation="horizontal"> <ImageButton - android:id="@+id/menu_prev_button" + android:id="@+id/menu_left_button" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" @@ -38,7 +38,7 @@ android:background="?android:attr/listDivider"/> <ImageButton - android:id="@+id/menu_next_button" + android:id="@+id/menu_right_button" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml index c198443415dd..c0aa1b3c4145 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml @@ -2,7 +2,7 @@ <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:horizontalSpacing="@dimen/a11ymenu_grid_layout_margin" android:listSelector="@android:color/transparent" android:numColumns="3" diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml index 28a633e5d17a..6be765528028 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml @@ -6,18 +6,16 @@ android:background="@drawable/view_background" > <LinearLayout - android:layout_width="@dimen/row_width" + android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> - <androidx.viewpager.widget.ViewPager + <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/table_margin_top" android:paddingBottom="@dimen/a11ymenu_layout_margin" - android:paddingLeft="@dimen/a11ymenu_layout_margin" - android:paddingRight="@dimen/a11ymenu_layout_margin" android:layout_gravity="center" android:gravity="center" /> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java index 20c63df885d2..78fbf01a1644 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java @@ -16,7 +16,11 @@ package com.android.systemui.accessibility.accessibilitymenu.view; +import static android.view.View.LAYOUT_DIRECTION_LTR; + +import android.content.res.Configuration; import android.graphics.Rect; +import android.text.TextUtils; import android.view.TouchDelegate; import android.view.View; import android.view.View.OnClickListener; @@ -37,46 +41,61 @@ public class A11yMenuFooter { public interface A11yMenuFooterCallBack { /** Calls back when user clicks the left button. */ - void onLeftButtonClicked(); + void onNextButtonClicked(); /** Calls back when user clicks the right button. */ - void onRightButtonClicked(); + void onPreviousButtonClicked(); } private final FooterButtonClickListener mFooterButtonClickListener; - private ImageButton mPreviousPageBtn; - private ImageButton mNextPageBtn; + private ImageButton mPageLeftBtn; + private ImageButton mPageRightBtn; private View mTopListDivider; private View mBottomListDivider; private final A11yMenuFooterCallBack mCallBack; + private final ViewGroup mMenuLayout; + private int mRightToLeftDirection = LAYOUT_DIRECTION_LTR; public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) { this.mCallBack = callBack; mFooterButtonClickListener = new FooterButtonClickListener(); configureFooterLayout(menuLayout); + mMenuLayout = menuLayout; } public @Nullable ImageButton getPreviousPageBtn() { - return mPreviousPageBtn; + return mRightToLeftDirection == LAYOUT_DIRECTION_LTR + ? mPageLeftBtn : mPageRightBtn; } public @Nullable ImageButton getNextPageBtn() { - return mNextPageBtn; + return mRightToLeftDirection == LAYOUT_DIRECTION_LTR + ? mPageRightBtn : mPageLeftBtn; + } + + /** Sets right to left direction of footer. */ + public void updateRightToLeftDirection(Configuration configuration) { + mRightToLeftDirection = TextUtils.getLayoutDirectionFromLocale( + configuration.getLocales().get(0)); + getPreviousPageBtn().setContentDescription(mMenuLayout.getResources().getString( + R.string.previous_button_content_description)); + getNextPageBtn().setContentDescription(mMenuLayout.getResources().getString( + R.string.next_button_content_description)); } private void configureFooterLayout(ViewGroup menuLayout) { ViewGroup footerContainer = menuLayout.findViewById(R.id.footerlayout); footerContainer.setVisibility(View.VISIBLE); - mPreviousPageBtn = menuLayout.findViewById(R.id.menu_prev_button); - mNextPageBtn = menuLayout.findViewById(R.id.menu_next_button); + mPageLeftBtn = menuLayout.findViewById(R.id.menu_left_button); + mPageRightBtn = menuLayout.findViewById(R.id.menu_right_button); mTopListDivider = menuLayout.findViewById(R.id.top_listDivider); mBottomListDivider = menuLayout.findViewById(R.id.bottom_listDivider); // Registers listeners for footer buttons. - setListener(mPreviousPageBtn); - setListener(mNextPageBtn); + setListener(mPageLeftBtn); + setListener(mPageRightBtn); menuLayout .getViewTreeObserver() @@ -85,8 +104,8 @@ public class A11yMenuFooter { @Override public void onGlobalLayout() { menuLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); - expandBtnTouchArea(mPreviousPageBtn, menuLayout); - expandBtnTouchArea(mNextPageBtn, (View) mNextPageBtn.getParent()); + expandBtnTouchArea(mPageLeftBtn, menuLayout); + expandBtnTouchArea(mPageRightBtn, (View) mPageRightBtn.getParent()); } }); } @@ -115,10 +134,10 @@ public class A11yMenuFooter { private class FooterButtonClickListener implements OnClickListener { @Override public void onClick(View view) { - if (view.getId() == R.id.menu_prev_button) { - mCallBack.onLeftButtonClicked(); - } else if (view.getId() == R.id.menu_next_button) { - mCallBack.onRightButtonClicked(); + if (view.getId() == getPreviousPageBtn().getId()) { + mCallBack.onPreviousButtonClicked(); + } else if (view.getId() == getNextPageBtn().getId()) { + mCallBack.onNextButtonClicked(); } } } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java index 6bea30fa8d08..de3c47235f6f 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java @@ -145,13 +145,14 @@ public class A11yMenuOverlayLayout { final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY); final Context context = mService.createDisplayContext(display).createWindowContext( TYPE_ACCESSIBILITY_OVERLAY, null); - mLayout = new FrameLayout(context); + mLayout = new A11yMenuFrameLayout(context); updateLayoutPosition(); inflateLayoutAndSetOnTouchListener(mLayout, context); mA11yMenuViewPager = new A11yMenuViewPager(mService, context); mA11yMenuViewPager.configureViewPagerAndFooter(mLayout, createShortcutList(), pageIndex); mWindowManager.addView(mLayout, mLayoutParameter); mLayout.setVisibility(lastVisibilityState); + mA11yMenuViewPager.updateFooterState(); return mLayout; } @@ -393,4 +394,16 @@ public class A11yMenuOverlayLayout { } }), timeoutDurationMs); } + + private class A11yMenuFrameLayout extends FrameLayout { + A11yMenuFrameLayout(@NonNull Context context) { + super(context); + } + + @Override + public void dispatchConfigurationChanged(Configuration newConfig) { + super.dispatchConfigurationChanged(newConfig); + mA11yMenuViewPager.mA11yMenuFooter.updateRightToLeftDirection(newConfig); + } + } } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java index b969017f7531..08bbf192591e 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Insets; import android.util.DisplayMetrics; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver.OnGlobalLayoutListener; @@ -29,7 +28,7 @@ import android.view.WindowManager; import android.view.WindowMetrics; import android.widget.GridView; -import androidx.viewpager.widget.ViewPager; +import androidx.viewpager2.widget.ViewPager2; import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService; import com.android.systemui.accessibility.accessibilitymenu.R; @@ -133,9 +132,9 @@ public class A11yMenuViewPager { * The pager widget, which handles animation and allows swiping horizontally to access previous * and next gridView pages. */ - protected ViewPager mViewPager; + protected ViewPager2 mViewPager; - private ViewPagerAdapter<GridView> mViewPagerAdapter; + private ViewPagerAdapter mViewPagerAdapter; private final List<GridView> mGridPageList = new ArrayList<>(); /** The footer, which provides buttons to switch between pages */ @@ -169,6 +168,8 @@ public class A11yMenuViewPager { initViewPager(); initChildPage(); mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks); + mA11yMenuFooter.updateRightToLeftDirection( + a11yMenuLayout.getResources().getConfiguration()); updateFooterState(); registerOnGlobalLayoutListener(); goToPage(pageIndex); @@ -177,18 +178,12 @@ public class A11yMenuViewPager { /** Initializes viewPager and its adapter. */ private void initViewPager() { mViewPager = mA11yMenuLayout.findViewById(R.id.view_pager); - mViewPagerAdapter = new ViewPagerAdapter<>(); + mViewPagerAdapter = new ViewPagerAdapter(mService); + mViewPager.setOffscreenPageLimit(2); mViewPager.setAdapter(mViewPagerAdapter); mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER); - mViewPager.addOnPageChangeListener( - new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrollStateChanged(int state) {} - - @Override - public void onPageScrolled( - int position, float positionOffset, int positionOffsetPixels) {} - + mViewPager.registerOnPageChangeCallback( + new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { updateFooterState(); @@ -206,31 +201,14 @@ public class A11yMenuViewPager { mGridPageList.clear(); } - // Generate pages by calculating # of items per grid. - for (List<A11yMenuShortcut> page : GridViewParams.generateShortcutSubLists( - GridViewParams.getGridItemCount(mService), mA11yMenuShortcutList) - ) { - addGridPage(page); - } - - mViewPagerAdapter.set(mGridPageList); - } - - private void addGridPage(List<A11yMenuShortcut> shortcutDataListInPage) { - LayoutInflater inflater = LayoutInflater.from(mDisplayContext); - View view = inflater.inflate(R.layout.grid_view, null); - GridView gridView = view.findViewById(R.id.gridview); - A11yMenuAdapter adapter = new A11yMenuAdapter( - mService, mDisplayContext, shortcutDataListInPage); - gridView.setNumColumns(GridViewParams.getGridColumnCount(mService)); - gridView.setAdapter(adapter); - mGridPageList.add(gridView); + mViewPagerAdapter.set(GridViewParams.generateShortcutSubLists( + GridViewParams.getGridItemCount(mService), mA11yMenuShortcutList)); } /** Updates footer's state by index of current page in view pager. */ - private void updateFooterState() { + public void updateFooterState() { int currentPage = mViewPager.getCurrentItem(); - int lastPage = mViewPager.getAdapter().getCount() - 1; + int lastPage = mViewPager.getAdapter().getItemCount() - 1; mA11yMenuFooter.getPreviousPageBtn().setEnabled(currentPage > 0); mA11yMenuFooter.getNextPageBtn().setEnabled(currentPage < lastPage); } @@ -239,7 +217,7 @@ public class A11yMenuViewPager { if (mViewPager == null) { return; } - if ((pageIndex >= 0) && (pageIndex < mViewPager.getAdapter().getCount())) { + if ((pageIndex >= 0) && (pageIndex < mViewPager.getAdapter().getItemCount())) { mViewPager.setCurrentItem(pageIndex); } } @@ -341,7 +319,7 @@ public class A11yMenuViewPager { protected A11yMenuFooterCallBack mFooterCallbacks = new A11yMenuFooterCallBack() { @Override - public void onLeftButtonClicked() { + public void onPreviousButtonClicked() { // Moves to previous page. int targetPage = mViewPager.getCurrentItem() - 1; goToPage(targetPage); @@ -349,7 +327,7 @@ public class A11yMenuViewPager { } @Override - public void onRightButtonClicked() { + public void onNextButtonClicked() { // Moves to next page. int targetPage = mViewPager.getCurrentItem() + 1; goToPage(targetPage); diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java index 5670d72842f4..43ec9561f4db 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java @@ -16,55 +16,64 @@ package com.android.systemui.accessibility.accessibilitymenu.view; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.GridView; -import androidx.viewpager.widget.PagerAdapter; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService; +import com.android.systemui.accessibility.accessibilitymenu.R; +import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut; import java.util.List; /** The pager adapter, which provides the pages to the view pager widget. */ -class ViewPagerAdapter<T extends View> extends PagerAdapter { - - /** The widget list in each page of view pager. */ - private List<T> mWidgetList; +class ViewPagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { - ViewPagerAdapter() {} + /** List of shortcuts, split into sub lists per page */ + private List<List<A11yMenuShortcut>> mShortcutList; + private final AccessibilityMenuService mService; - public void set(List<T> tList) { - mWidgetList = tList; - notifyDataSetChanged(); + ViewPagerAdapter(AccessibilityMenuService service) { + mService = service; } - @Override - public int getCount() { - if (mWidgetList == null) { - return 0; - } - return mWidgetList.size(); + public void set(List<List<A11yMenuShortcut>> tList) { + mShortcutList = tList; + notifyDataSetChanged(); } + @NonNull @Override - public int getItemPosition(Object object) { - return POSITION_NONE; + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + View view = inflater.inflate(R.layout.grid_view, parent, false); + return new MenuViewHolder(view.findViewById(R.id.gridview)); } @Override - public boolean isViewFromObject(View view, Object object) { - return view == object; + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + A11yMenuAdapter adapter = new A11yMenuAdapter( + mService, holder.itemView.getContext(), mShortcutList.get(position)); + GridView gridView = (GridView) holder.itemView; + gridView.setNumColumns(A11yMenuViewPager.GridViewParams.getGridColumnCount(mService)); + gridView.setAdapter(adapter); } @Override - public Object instantiateItem(ViewGroup container, int position) { - if (mWidgetList == null) { - return null; + public int getItemCount() { + if (mShortcutList == null) { + return 0; } - container.addView(mWidgetList.get(position)); - return mWidgetList.get(position); + return mShortcutList.size(); } - @Override - public void destroyItem(ViewGroup container, int position, Object object) { - container.removeView((View) object); + static class MenuViewHolder extends RecyclerView.ViewHolder { + MenuViewHolder(View itemView) { + super(itemView); + } } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig index 8860452905bd..52512464cb30 100644 --- a/packages/SystemUI/aconfig/accessibility.aconfig +++ b/packages/SystemUI/aconfig/accessibility.aconfig @@ -4,6 +4,16 @@ container: "system" # NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors. flag { + name: "add_black_background_for_window_magnifier" + namespace: "accessibility" + description: "Set the background for SurfaceView in window magnification black." + bug: "299981434" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "create_windowless_window_magnifier" namespace: "accessibility" description: "Uses SurfaceControlViewHost to create the magnifier for window magnification." diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index cdbac338e0be..047c097c8847 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -281,13 +281,6 @@ flag { } flag { - name: "qs_new_pipeline" - namespace: "systemui" - description: "Use the new pipeline for Quick Settings. Should have no behavior changes." - bug: "241772429" -} - -flag { name: "qs_new_tiles" namespace: "systemui" description: "Use the new tiles in the Quick Settings. Should have no behavior changes." @@ -387,6 +380,17 @@ flag { } flag { + name: "status_bar_stop_updating_window_height" + namespace: "systemui" + description: "Don't have PhoneStatusBarView manually trigger an update of the height in " + "StatusBarWindowController" + bug: "360115167" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "compose_bouncer" namespace: "systemui" description: "Use the new compose bouncer in SystemUI" @@ -998,6 +1002,16 @@ flag { } flag { + name: "communal_widget_trampoline_fix" + namespace: "systemui" + description: "fixes activity starts caused by non-activity trampolines from widgets." + bug: "350468769" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "app_clips_backlinks" namespace: "systemui" description: "Enables Backlinks improvement feature in App Clips" @@ -1035,6 +1049,13 @@ flag { } flag { + name: "media_controls_button_media3" + namespace: "systemui" + description: "Enable media action buttons updates using media3" + bug: "360196209" +} + +flag { namespace: "systemui" name: "enable_view_capture_tracing" description: "Enables view capture tracing in System UI." diff --git a/packages/SystemUI/compose/core/src/com/android/compose/PlatformButtons.kt b/packages/SystemUI/compose/core/src/com/android/compose/PlatformButtons.kt index a18b460cb168..a5f8057b524f 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/PlatformButtons.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/PlatformButtons.kt @@ -21,8 +21,7 @@ import androidx.annotation.DrawableRes import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.heightIn import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon @@ -32,7 +31,6 @@ import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.android.compose.theme.LocalAndroidColorScheme @@ -42,11 +40,10 @@ fun PlatformButton( modifier: Modifier = Modifier, enabled: Boolean = true, colors: ButtonColors = filledButtonColors(), - verticalPadding: Dp = DefaultPlatformButtonVerticalPadding, content: @Composable RowScope.() -> Unit, ) { androidx.compose.material3.Button( - modifier = modifier.padding(vertical = verticalPadding).height(36.dp), + modifier = modifier.heightIn(min = 36.dp), colors = colors, contentPadding = ButtonPaddings, onClick = onClick, @@ -63,11 +60,10 @@ fun PlatformOutlinedButton( enabled: Boolean = true, colors: ButtonColors = outlineButtonColors(), border: BorderStroke? = outlineButtonBorder(), - verticalPadding: Dp = DefaultPlatformButtonVerticalPadding, content: @Composable RowScope.() -> Unit, ) { androidx.compose.material3.OutlinedButton( - modifier = modifier.padding(vertical = verticalPadding).height(36.dp), + modifier = modifier.heightIn(min = 36.dp), enabled = enabled, colors = colors, border = border, @@ -118,7 +114,6 @@ fun PlatformIconButton( } } -private val DefaultPlatformButtonVerticalPadding = 6.dp private val ButtonPaddings = PaddingValues(horizontal = 16.dp, vertical = 8.dp) @Composable diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt index f655ac1d207b..d164eab5afeb 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt @@ -95,7 +95,7 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModel -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.MessageViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel @@ -114,7 +114,7 @@ import platform.test.motion.compose.values.motionTestValues @Composable fun BouncerContent( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { @@ -128,7 +128,7 @@ fun BouncerContent( @VisibleForTesting fun BouncerContent( layout: BouncerSceneLayout, - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier ) { @@ -173,7 +173,7 @@ fun BouncerContent( */ @Composable private fun StandardLayout( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val isHeightExpanded = @@ -235,7 +235,7 @@ private fun StandardLayout( */ @Composable private fun SplitLayout( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethod by viewModel.authMethodViewModel.collectAsStateWithLifecycle() @@ -326,7 +326,7 @@ private fun SplitLayout( */ @Composable private fun BesideUserSwitcherLayout( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val layoutDirection = LocalLayoutDirection.current @@ -461,7 +461,7 @@ private fun BesideUserSwitcherLayout( /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */ @Composable private fun BelowUserSwitcherLayout( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { Column( @@ -506,7 +506,7 @@ private fun BelowUserSwitcherLayout( @Composable private fun FoldAware( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, aboveFold: @Composable BoxScope.() -> Unit, belowFold: @Composable BoxScope.() -> Unit, modifier: Modifier = Modifier, @@ -649,7 +649,7 @@ private fun StatusMessage( */ @Composable private fun OutputArea( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethodViewModel: AuthMethodBouncerViewModel? by @@ -677,7 +677,7 @@ private fun OutputArea( */ @Composable private fun InputArea( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, pinButtonRowVerticalSpacing: Dp, centerPatternDotsVertically: Boolean, modifier: Modifier = Modifier, @@ -706,7 +706,7 @@ private fun InputArea( @Composable private fun ActionArea( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val actionButton: BouncerActionButtonModel? by @@ -774,7 +774,7 @@ private fun ActionArea( @Composable private fun Dialog( - bouncerViewModel: BouncerViewModel, + bouncerViewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, ) { val dialogViewModel by bouncerViewModel.dialogViewModel.collectAsStateWithLifecycle() @@ -803,7 +803,7 @@ private fun Dialog( /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */ @Composable private fun UserSwitcher( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { if (!viewModel.isUserSwitcherVisible) { @@ -884,7 +884,7 @@ private fun UserSwitcher( @Composable private fun UserSwitcherDropdownMenu( isExpanded: Boolean, - items: List<BouncerViewModel.UserSwitcherDropdownItemViewModel>, + items: List<BouncerSceneContentViewModel.UserSwitcherDropdownItemViewModel>, onDismissed: () -> Unit, ) { val context = LocalContext.current diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt index 9fd30b499595..aeba67bd121c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt @@ -27,9 +27,11 @@ import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import javax.inject.Inject @@ -51,23 +53,37 @@ object Bouncer { class BouncerScene @Inject constructor( - private val viewModel: BouncerViewModel, + private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory, + private val contentViewModelFactory: BouncerSceneContentViewModel.Factory, private val dialogFactory: BouncerDialogFactory, ) : ComposableScene { override val key = Scenes.Bouncer + private val actionsViewModel: BouncerSceneActionsViewModel by lazy { + actionsViewModelFactory.create() + } + override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - viewModel.destinationScenes + actionsViewModel.actions + + override suspend fun activate(): Nothing { + actionsViewModel.activate() + } @Composable override fun SceneScope.Content( modifier: Modifier, - ) = BouncerScene(viewModel, dialogFactory, modifier) + ) = + BouncerScene( + viewModel = rememberViewModel { contentViewModelFactory.create() }, + dialogFactory = dialogFactory, + modifier = modifier, + ) } @Composable private fun SceneScope.BouncerScene( - viewModel: BouncerViewModel, + viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index 97900652bd99..91a88bc7aa97 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -1407,7 +1407,10 @@ fun AccessibilityContainer(viewModel: BaseCommunalViewModel, content: @Composabl R.string.accessibility_action_label_close_communal_hub ) ) { - viewModel.changeScene(CommunalScenes.Blank) + viewModel.changeScene( + CommunalScenes.Blank, + "closed by accessibility" + ) true }, CustomAccessibilityAction( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt index 7fe1b3e619c1..7f059d766307 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt @@ -49,7 +49,7 @@ constructor( override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions - override suspend fun activate() { + override suspend fun activate(): Nothing { actionsViewModel.activate() } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt index 0cb8bd3a7efb..666e324c8d36 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt @@ -72,7 +72,7 @@ constructor( override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions - override suspend fun activate() { + override suspend fun activate(): Nothing { actionsViewModel.activate() } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 12edd049c0e1..e0647242b7ad 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -92,7 +92,8 @@ import com.android.systemui.notifications.ui.composable.NotificationStackCutoffG import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS -import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel +import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneActionsViewModel +import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes @@ -120,8 +121,9 @@ class QuickSettingsScene constructor( private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, - private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, + private val actionsViewModelFactory: QuickSettingsSceneActionsViewModel.Factory, + private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, @@ -130,8 +132,16 @@ constructor( ) : ComposableScene { override val key = Scenes.QuickSettings + private val actionsViewModel: QuickSettingsSceneActionsViewModel by lazy { + actionsViewModelFactory.create() + } + override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - viewModel.destinationScenes + actionsViewModel.actions + + override suspend fun activate(): Nothing { + actionsViewModel.activate() + } @Composable override fun SceneScope.Content( @@ -139,7 +149,7 @@ constructor( ) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), - viewModel = viewModel, + viewModelFactory = contentViewModelFactory, notificationsPlaceholderViewModel = rememberViewModel { notificationsPlaceholderViewModelFactory.create() }, createTintedIconManager = tintedIconManagerFactory::create, @@ -156,7 +166,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, - viewModel: QuickSettingsSceneViewModel, + viewModelFactory: QuickSettingsSceneContentViewModel.Factory, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, @@ -168,6 +178,7 @@ private fun SceneScope.QuickSettingsScene( ) { val cutoutLocation = LocalDisplayCutout.current.location + val viewModel = rememberViewModel { viewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel { viewModel.brightnessMirrorViewModelFactory.create() } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt index eea00c4f2935..fb7c42254caa 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt @@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -42,6 +40,7 @@ import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer +import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.ui.composable.LockscreenContent import com.android.systemui.lifecycle.rememberViewModel @@ -114,7 +113,7 @@ constructor( } @Composable -private fun ShadeBody( +fun ShadeBody( viewModel: QuickSettingsContainerViewModel, ) { val isEditing by viewModel.editModeViewModel.isEditing.collectAsStateWithLifecycle() @@ -131,6 +130,7 @@ private fun ShadeBody( } else { QuickSettingsLayout( viewModel = viewModel, + modifier = Modifier.sysuiResTag("quick_settings_panel") ) } } @@ -158,11 +158,6 @@ private fun QuickSettingsLayout( Modifier.fillMaxWidth().heightIn(max = QuickSettingsShade.Dimensions.GridMaxHeight), viewModel.editModeViewModel::startEditing, ) - Button( - onClick = { viewModel.editModeViewModel.startEditing() }, - ) { - Text("Edit mode") - } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt index f15e87b4514d..3e221056c2db 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt @@ -58,7 +58,7 @@ constructor( override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions - override suspend fun activate() { + override suspend fun activate(): Nothing { actionsViewModel.activate() } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index 7920e74eff01..d15bda0b362b 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -56,6 +56,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.colorResource @@ -88,6 +89,8 @@ import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.controls.ui.view.MediaHostState +import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.COLLAPSED +import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.EXPANDED import com.android.systemui.media.dagger.MediaModule.QS_PANEL import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL import com.android.systemui.notifications.ui.composable.NotificationScrollingStack @@ -110,6 +113,7 @@ import com.android.systemui.statusbar.notification.stack.ui.viewmodel.Notificati import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager +import com.android.systemui.util.Utils import dagger.Lazy import javax.inject.Inject import javax.inject.Named @@ -163,7 +167,7 @@ constructor( actionsViewModelFactory.create() } - override suspend fun activate() { + override suspend fun activate(): Nothing { actionsViewModel.activate() } @@ -260,6 +264,11 @@ private fun SceneScope.SingleShade( shadeSession: SaveableSession, ) { val cutoutLocation = LocalDisplayCutout.current.location + val isLandscape = LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact + val usingCollapsedLandscapeMedia = + Utils.useCollapsedMediaInLandscape(LocalContext.current.resources) + val isExpanded = !usingCollapsedLandscapeMedia || !isLandscape + mediaHost.expansion = if (isExpanded) EXPANDED else COLLAPSED val maxNotifScrimTop = remember { mutableStateOf(0f) } val tileSquishiness by @@ -275,9 +284,7 @@ private fun SceneScope.SingleShade( layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) || layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade) // Media is visible and we are in landscape on a small height screen - val mediaInRow = - isMediaVisible && - LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact + val mediaInRow = isMediaVisible && isLandscape val mediaOffset by animateSceneDpAsState(value = InQQS, key = MediaLandscapeTopOffset, canOverflow = false) diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt index 68a6c9836875..920c234174d0 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt @@ -17,7 +17,6 @@ package com.android.compose.animation.scene import com.android.compose.animation.scene.content.state.TransitionState -import kotlin.math.absoluteValue import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -63,47 +62,30 @@ internal fun CoroutineScope.animateToScene( if (transitionState.toScene == target) { // The user is currently swiping to [target] but didn't release their pointer yet: // animate the progress to `1`. - check(transitionState.fromScene == transitionState.currentScene) - val progress = transitionState.progress - if ((1f - progress).absoluteValue < ProgressVisibilityThreshold) { - // The transition is already finished (progress ~= 1): no need to animate. We - // finish the current transition early to make sure that the current state - // change is committed. - layoutState.finishTransition(transitionState, target) - null - } else { - // The transition is in progress: start the canned animation at the same - // progress as it was in. - animateToScene( - layoutState, - target, - transitionKey, - isInitiatedByUserInput, - replacedTransition = transitionState, - ) - } + + // The transition is in progress: start the canned animation at the same + // progress as it was in. + animateToScene( + layoutState, + target, + transitionKey, + isInitiatedByUserInput, + replacedTransition = transitionState, + ) } else if (transitionState.fromScene == target) { // There is a transition from [target] to another scene: simply animate the same // transition progress to `0`. check(transitionState.toScene == transitionState.currentScene) - val progress = transitionState.progress - if (progress.absoluteValue < ProgressVisibilityThreshold) { - // The transition is at progress ~= 0: no need to animate.We finish the current - // transition early to make sure that the current state change is committed. - layoutState.finishTransition(transitionState, target) - null - } else { - animateToScene( - layoutState, - target, - transitionKey, - isInitiatedByUserInput, - reversed = true, - replacedTransition = transitionState, - ) - } + animateToScene( + layoutState, + target, + transitionKey, + isInitiatedByUserInput, + reversed = true, + replacedTransition = transitionState, + ) } else { // Generic interruption; the current transition is neither from or to [target]. val interruptionResult = @@ -185,7 +167,7 @@ private fun CoroutineScope.animateToScene( oneOffAnimation = oneOffAnimation, targetProgress = targetProgress, startTransition = { layoutState.startTransition(transition, chain) }, - finishTransition = { layoutState.finishTransition(transition, targetScene) }, + finishTransition = { layoutState.finishTransition(transition) }, ) return transition diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt index 712fe6b2ff50..9c3896b90124 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt @@ -777,7 +777,8 @@ private class SwipeTransition( fun snapToScene(scene: SceneKey) { cancelOffsetAnimation() - layoutState.finishTransition(this, idleScene = scene) + check(currentScene == scene) + layoutState.finishTransition(this) } override fun finish(): Job { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt index b329534e6e3a..3487730945da 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt @@ -81,6 +81,7 @@ internal fun Modifier.multiPointerDraggable( enabled: () -> Boolean, startDragImmediately: (startedPosition: Offset) -> Boolean, onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController, + onFirstPointerDown: () -> Unit = {}, swipeDetector: SwipeDetector = DefaultSwipeDetector, dispatcher: NestedScrollDispatcher, ): Modifier = @@ -90,6 +91,7 @@ internal fun Modifier.multiPointerDraggable( enabled, startDragImmediately, onDragStarted, + onFirstPointerDown, swipeDetector, dispatcher, ) @@ -101,6 +103,7 @@ private data class MultiPointerDraggableElement( private val startDragImmediately: (startedPosition: Offset) -> Boolean, private val onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController, + private val onFirstPointerDown: () -> Unit, private val swipeDetector: SwipeDetector, private val dispatcher: NestedScrollDispatcher, ) : ModifierNodeElement<MultiPointerDraggableNode>() { @@ -110,6 +113,7 @@ private data class MultiPointerDraggableElement( enabled = enabled, startDragImmediately = startDragImmediately, onDragStarted = onDragStarted, + onFirstPointerDown = onFirstPointerDown, swipeDetector = swipeDetector, dispatcher = dispatcher, ) @@ -119,6 +123,7 @@ private data class MultiPointerDraggableElement( node.enabled = enabled node.startDragImmediately = startDragImmediately node.onDragStarted = onDragStarted + node.onFirstPointerDown = onFirstPointerDown node.swipeDetector = swipeDetector } } @@ -129,6 +134,7 @@ internal class MultiPointerDraggableNode( var startDragImmediately: (startedPosition: Offset) -> Boolean, var onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController, + var onFirstPointerDown: () -> Unit, var swipeDetector: SwipeDetector = DefaultSwipeDetector, private val dispatcher: NestedScrollDispatcher, ) : @@ -225,6 +231,7 @@ internal class MultiPointerDraggableNode( startedPosition = null } else if (startedPosition == null) { startedPosition = pointers.first().position + onFirstPointerDown() } } } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt index fe16ef75118b..2fbdf7c1a501 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt @@ -129,7 +129,7 @@ private class PredictiveBackTransition( try { animatable.animateTo(targetProgress) } finally { - state.finishTransition(this@PredictiveBackTransition, scene) + state.finishTransition(this@PredictiveBackTransition) } } .also { animationJob = it } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt index a6c6a80941fc..44f5964feacb 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt @@ -167,8 +167,6 @@ internal class MutableSceneTransitionLayoutStateImpl( override val transitionState: TransitionState get() = transitionStates.last() - private val activeTransitionLinks = mutableMapOf<StateLink, LinkedTransition>() - override val currentTransitions: List<TransitionState.Transition> get() { if (transitionStates.last() is TransitionState.Idle) { @@ -180,12 +178,8 @@ internal class MutableSceneTransitionLayoutStateImpl( } } - /** - * The mapping of transitions that are finished, i.e. for which [finishTransition] was called, - * to their idle scene. - */ - @VisibleForTesting - internal val finishedTransitions = mutableMapOf<TransitionState.Transition, SceneKey>() + /** The transitions that are finished, i.e. for which [finishTransition] was called. */ + @VisibleForTesting internal val finishedTransitions = mutableSetOf<TransitionState.Transition>() internal fun checkThread() { val current = Thread.currentThread() @@ -261,7 +255,7 @@ internal class MutableSceneTransitionLayoutStateImpl( } // Handle transition links. - cancelActiveTransitionLinks() + currentTransition?.let { cancelActiveTransitionLinks(it) } setupTransitionLinks(transition) if (!enableInterruptions) { @@ -289,8 +283,7 @@ internal class MutableSceneTransitionLayoutStateImpl( // Force finish all transitions. while (currentTransitions.isNotEmpty()) { - val transition = transitionStates[0] as TransitionState.Transition - finishTransition(transition, transition.currentScene) + finishTransition(transitionStates[0] as TransitionState.Transition) } // We finished all transitions, so we are now idle. We remove this state so that @@ -328,18 +321,17 @@ internal class MutableSceneTransitionLayoutStateImpl( ) } - private fun cancelActiveTransitionLinks() { - for ((link, linkedTransition) in activeTransitionLinks) { - link.target.finishTransition(linkedTransition, linkedTransition.currentScene) + private fun cancelActiveTransitionLinks(transition: TransitionState.Transition) { + transition.activeTransitionLinks.forEach { (link, linkedTransition) -> + link.target.finishTransition(linkedTransition) } - activeTransitionLinks.clear() + transition.activeTransitionLinks.clear() } - private fun setupTransitionLinks(transitionState: TransitionState) { - if (transitionState !is TransitionState.Transition) return + private fun setupTransitionLinks(transition: TransitionState.Transition) { stateLinks.fastForEach { stateLink -> val matchingLinks = - stateLink.transitionLinks.fastFilter { it.isMatchingLink(transitionState) } + stateLink.transitionLinks.fastFilter { it.isMatchingLink(transition) } if (matchingLinks.isEmpty()) return@fastForEach if (matchingLinks.size > 1) error("More than one link matched.") @@ -350,31 +342,27 @@ internal class MutableSceneTransitionLayoutStateImpl( val linkedTransition = LinkedTransition( - originalTransition = transitionState, + originalTransition = transition, fromScene = targetCurrentScene, toScene = matchingLink.targetTo, key = matchingLink.targetTransitionKey, ) stateLink.target.startTransition(linkedTransition) - activeTransitionLinks[stateLink] = linkedTransition + transition.activeTransitionLinks[stateLink] = linkedTransition } } /** - * Notify that [transition] was finished and that we should settle to [idleScene]. This will do - * nothing if [transition] was interrupted since it was started. + * Notify that [transition] was finished and that it settled to its + * [currentScene][TransitionState.currentScene]. This will do nothing if [transition] was + * interrupted since it was started. */ - internal fun finishTransition(transition: TransitionState.Transition, idleScene: SceneKey) { + internal fun finishTransition(transition: TransitionState.Transition) { checkThread() - val existingIdleScene = finishedTransitions[transition] - if (existingIdleScene != null) { + if (finishedTransitions.contains(transition)) { // This transition was already finished. - check(idleScene == existingIdleScene) { - "Transition $transition was finished multiple times with different " + - "idleScene ($existingIdleScene != $idleScene)" - } return } @@ -386,15 +374,15 @@ internal class MutableSceneTransitionLayoutStateImpl( check(transitionStates.fastAll { it is TransitionState.Transition }) - // Mark this transition as finished and save the scene it is settling at. - finishedTransitions[transition] = idleScene + // Mark this transition as finished. + finishedTransitions.add(transition) // Finish all linked transitions. - finishActiveTransitionLinks(idleScene) + finishActiveTransitionLinks(transition) - // Keep a reference to the idle scene of the last removed transition, in case we remove all - // transitions and should settle to Idle. - var lastRemovedIdleScene: SceneKey? = null + // Keep a reference to the last transition, in case we remove all transitions and should + // settle to Idle. + val lastTransition = transitionStates.last() // Remove all first n finished transitions. var i = 0 @@ -407,14 +395,14 @@ internal class MutableSceneTransitionLayoutStateImpl( } // Remove the transition from the set of finished transitions. - lastRemovedIdleScene = finishedTransitions.remove(t) + finishedTransitions.remove(t) i++ } // If all transitions are finished, we are idle. if (i == nStates) { check(finishedTransitions.isEmpty()) - this.transitionStates = listOf(TransitionState.Idle(checkNotNull(lastRemovedIdleScene))) + this.transitionStates = listOf(TransitionState.Idle(lastTransition.currentScene)) } else if (i > 0) { this.transitionStates = transitionStates.subList(fromIndex = i, toIndex = nStates) } @@ -426,28 +414,18 @@ internal class MutableSceneTransitionLayoutStateImpl( // Force finish all transitions. while (currentTransitions.isNotEmpty()) { val transition = transitionStates[0] as TransitionState.Transition - finishTransition(transition, transition.currentScene) + finishTransition(transition) } check(transitionStates.size == 1) transitionStates = listOf(TransitionState.Idle(scene)) } - private fun finishActiveTransitionLinks(idleScene: SceneKey) { - val previousTransition = this.transitionState as? TransitionState.Transition ?: return - for ((link, linkedTransition) in activeTransitionLinks) { - if (previousTransition.fromScene == idleScene) { - // The transition ended by arriving at the fromScene, move link to Idle(fromScene). - link.target.finishTransition(linkedTransition, linkedTransition.fromScene) - } else if (previousTransition.toScene == idleScene) { - // The transition ended by arriving at the toScene, move link to Idle(toScene). - link.target.finishTransition(linkedTransition, linkedTransition.toScene) - } else { - // The transition was interrupted by something else, we reset to initial state. - link.target.finishTransition(linkedTransition, linkedTransition.fromScene) - } + private fun finishActiveTransitionLinks(transition: TransitionState.Transition) { + for ((link, linkedTransition) in transition.activeTransitionLinks) { + link.target.finishTransition(linkedTransition) } - activeTransitionLinks.clear() + transition.activeTransitionLinks.clear() } /** @@ -465,31 +443,21 @@ internal class MutableSceneTransitionLayoutStateImpl( fun isProgressCloseTo(value: Float) = (progress - value).absoluteValue <= threshold - fun finishAllTransitions(lastTransitionIdleScene: SceneKey) { + fun finishAllTransitions() { // Force finish all transitions. while (currentTransitions.isNotEmpty()) { - val transition = transitionStates[0] as TransitionState.Transition - val idleScene = - if (transitionStates.size == 1) { - lastTransitionIdleScene - } else { - transition.currentScene - } - - finishTransition(transition, idleScene) + finishTransition(transitionStates[0] as TransitionState.Transition) } } - return when { - isProgressCloseTo(0f) -> { - finishAllTransitions(transition.fromScene) - true - } - isProgressCloseTo(1f) -> { - finishAllTransitions(transition.toScene) - true - } - else -> false + val shouldSnap = + (isProgressCloseTo(0f) && transition.currentScene == transition.fromScene) || + (isProgressCloseTo(1f) && transition.currentScene == transition.toScene) + return if (shouldSnap) { + finishAllTransitions() + true + } else { + false } } } diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt index f06214645144..d1e83bacf40a 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt @@ -67,6 +67,7 @@ private class SwipeToSceneNode( enabled = ::enabled, startDragImmediately = ::startDragImmediately, onDragStarted = draggableHandler::onDragStarted, + onFirstPointerDown = ::onFirstPointerDown, swipeDetector = swipeDetector, dispatcher = dispatcher, ) @@ -101,6 +102,15 @@ private class SwipeToSceneNode( delegate(ScrollBehaviorOwnerNode(draggableHandler.nestedScrollKey, nestedScrollHandlerImpl)) } + private fun onFirstPointerDown() { + // When we drag our finger across the screen, the NestedScrollConnection keeps track of all + // the scroll events until we lift our finger. However, in some cases, the connection might + // not receive the "up" event. This can lead to an incorrect initial state for the gesture. + // To prevent this issue, we can call the reset() method when the first finger touches the + // screen. This ensures that the NestedScrollConnection starts from a correct state. + nestedScrollHandlerImpl.connection.reset() + } + override fun onDetach() { // Make sure we reset the scroll connection when this modifier is removed from composition nestedScrollHandlerImpl.connection.reset() diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt index 79b38563b8f9..5e963811729a 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt @@ -245,9 +245,7 @@ interface OverscrollScope : Density { interface ElementContentPicker { /** * Return the content in which [element] should be drawn (when using `Modifier.element(key)`) or - * composed (when using `MovableElement(key)`) during the given [transition]. If this element - * should not be drawn or composed in neither [transition.fromContent] nor - * [transition.toContent], return `null`. + * composed (when using `MovableElement(key)`) during the given [transition]. * * Important: For [MovableElements][ContentScope.MovableElement], this content picker will * *always* be used during transitions to decide whether we should compose that element in a diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt index add393441794..0bd676bb9858 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt @@ -29,6 +29,8 @@ import com.android.compose.animation.scene.SceneTransitionLayoutImpl import com.android.compose.animation.scene.TransformationSpec import com.android.compose.animation.scene.TransformationSpecImpl import com.android.compose.animation.scene.TransitionKey +import com.android.compose.animation.scene.transition.link.LinkedTransition +import com.android.compose.animation.scene.transition.link.StateLink import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -110,6 +112,9 @@ sealed interface ContentState<out T : ContentKey> { */ private var interruptionDecay: Animatable<Float, AnimationVector1D>? = null + /** The map of active links that connects this transition to other transitions. */ + internal val activeTransitionLinks = mutableMapOf<StateLink, LinkedTransition>() + init { check(fromContent != toContent) check( @@ -131,7 +136,7 @@ sealed interface ContentState<out T : ContentKey> { * animation is complete or cancel it to snap the animation. Calling [finish] multiple * times will return the same [Job]. */ - abstract fun finish(): Job + internal abstract fun finish(): Job /** * Whether we are transitioning. If [from] or [to] is empty, we will also check that they diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt index 228f7ba48d3e..16fb533bbe06 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt @@ -129,7 +129,11 @@ class PriorityNestedScrollConnection( return onPriorityStop(available) } - /** Method to call before destroying the object or to reset the initial state. */ + /** + * Method to call before destroying the object or to reset the initial state. + * + * TODO(b/303224944) This method should be removed. + */ fun reset() { // Step 3c: To ensure that an onStop is always called for every onStart. onPriorityStop(velocity = Velocity.Zero) diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt index 75f44ff9cfe0..60cefb0c0ac4 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt @@ -1380,8 +1380,8 @@ class ElementTest { // Manually finish the transition. rule.runOnUiThread { - state.finishTransition(aToB, SceneB) - state.finishTransition(bToC, SceneC) + state.finishTransition(aToB) + state.finishTransition(bToC) } rule.waitForIdle() assertThat(state.transitionState).isIdle() @@ -1482,7 +1482,7 @@ class ElementTest { // Manually finish A => B so only B => C is remaining. bToCInterruptionProgress = 0f - rule.runOnUiThread { state.finishTransition(aToB, SceneB) } + rule.runOnUiThread { state.finishTransition(aToB) } rule .onNode(isElement(TestElements.Foo, SceneB)) .assertPositionInRootIsEqualTo(offsetInB.x, offsetInB.y) @@ -2002,6 +2002,7 @@ class ElementTest { transition( from = SceneB, to = SceneC, + current = { SceneB }, progress = { 0f }, interruptionProgress = { interruptionProgress }, onFinish = neverFinish(), @@ -2018,8 +2019,8 @@ class ElementTest { // 100%. We should be at (20dp, 20dp), unless the interruption deltas have not been // correctly cleaned. rule.runOnUiThread { - state.finishTransition(aToB, idleScene = SceneB) - state.finishTransition(bToC, idleScene = SceneB) + state.finishTransition(aToB) + state.finishTransition(bToC) state.startTransition( transition( from = SceneB, diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt index 9ebc42650d45..d8a06f54e74b 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt @@ -23,6 +23,9 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.platform.LocalViewConfiguration @@ -266,4 +269,38 @@ class NestedScrollToSceneTest { val transition = assertThat(state.transitionState).isTransition() assertThat(transition).hasProgress(0.5f) } + + @Test + fun resetScrollTracking_afterMissingPointerUpEvent() { + var canScroll = true + var hasScrollable by mutableStateOf(true) + val state = setup2ScenesAndScrollTouchSlop { + if (hasScrollable) { + Modifier.scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical) + } else { + Modifier + } + } + + // The gesture is consumed by the component in the scene. + scrollUp(percent = 0.2f) + + // STL keeps track of the scroll consumed. The scene remains in Idle. + assertThat(state.transitionState).isIdle() + + // The scrollable component disappears, and does not send the signal (pointer up) to reset + // the consumed amount. + hasScrollable = false + pointerUp() + + // A new scrollable component appears and allows the scene to consume the scroll. + hasScrollable = true + canScroll = false + pointerDownAndScrollTouchSlop() + scrollUp(percent = 0.2f) + + // STL can only start the transition if it has reset the amount of scroll consumed. + val transition = assertThat(state.transitionState).isTransition() + assertThat(transition).hasProgress(0.2f) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt index 6b417ee5a468..c8ac580bf5ba 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt @@ -18,7 +18,9 @@ package com.android.compose.animation.scene import android.util.Log import androidx.compose.foundation.gestures.Orientation +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.compose.animation.scene.TestScenes.SceneA @@ -110,16 +112,6 @@ class SceneTransitionLayoutStateTest { } @Test - fun setTargetScene_transitionToOriginalScene() = runMonotonicClockTest { - val state = MutableSceneTransitionLayoutState(SceneA) - assertThat(state.setTargetScene(SceneB, coroutineScope = this)).isNotNull() - - // Progress is 0f, so we don't animate at all and directly snap back to A. - assertThat(state.setTargetScene(SceneA, coroutineScope = this)).isNull() - assertThat(state.transitionState).isEqualTo(TransitionState.Idle(SceneA)) - } - - @Test fun setTargetScene_coroutineScopeCancelled() = runMonotonicClockTest { val state = MutableSceneTransitionLayoutState(SceneA) @@ -180,7 +172,7 @@ class SceneTransitionLayoutStateTest { assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() - childState.finishTransition(childTransition, SceneB) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneD)) } @@ -217,7 +209,7 @@ class SceneTransitionLayoutStateTest { assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() assertThat(parentParentState.isTransitioning(SceneB, SceneC)).isTrue() - childState.finishTransition(childTransition, SceneB) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneD)) assertThat(parentParentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) @@ -241,13 +233,13 @@ class SceneTransitionLayoutStateTest { fun linkedTransition_reverseTransitionIsNotLinked() { val (parentState, childState) = setupLinkedStates() - val childTransition = transition(SceneB, SceneA) + val childTransition = transition(SceneB, SceneA, current = { SceneB }) childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneB, SceneA)).isTrue() assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) - childState.finishTransition(childTransition, SceneB) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) } @@ -256,27 +248,15 @@ class SceneTransitionLayoutStateTest { fun linkedTransition_startsLinkAndFinishesLinkInFromState() { val (parentState, childState) = setupLinkedStates() - val childTransition = transition(SceneA, SceneB) + val childTransition = transition(SceneA, SceneB, current = { SceneA }) childState.startTransition(childTransition) - childState.finishTransition(childTransition, SceneA) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneA)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) } @Test - fun linkedTransition_startsLinkAndFinishesLinkInUnknownState() { - val (parentState, childState) = setupLinkedStates() - - val childTransition = transition(SceneA, SceneB) - childState.startTransition(childTransition) - - childState.finishTransition(childTransition, SceneD) - assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneD)) - assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) - } - - @Test fun linkedTransition_startsLinkButLinkedStateIsTakenOver() = runTest { val (parentState, childState) = setupLinkedStates() @@ -295,7 +275,7 @@ class SceneTransitionLayoutStateTest { childState.startTransition(childTransition) parentState.startTransition(parentTransition) - childState.finishTransition(childTransition, SceneB) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) assertThat(parentState.transitionState).isEqualTo(parentTransition) } @@ -341,7 +321,9 @@ class SceneTransitionLayoutStateTest { @Test fun snapToIdleIfClose_snapToStart() = runMonotonicClockTest { val state = MutableSceneTransitionLayoutStateImpl(SceneA, SceneTransitions.Empty) - state.startTransition(transition(from = SceneA, to = SceneB, progress = { 0.2f })) + state.startTransition( + transition(from = SceneA, to = SceneB, current = { SceneA }, progress = { 0.2f }) + ) assertThat(state.isTransitioning()).isTrue() // Ignore the request if the progress is not close to 0 or 1, using the threshold. @@ -399,6 +381,31 @@ class SceneTransitionLayoutStateTest { } @Test + fun snapToIdleIfClose_closeButNotCurrentScene() = runMonotonicClockTest { + val state = MutableSceneTransitionLayoutStateImpl(SceneA, SceneTransitions.Empty) + var progress by mutableStateOf(0f) + var currentScene by mutableStateOf(SceneB) + state.startTransition( + transition( + from = SceneA, + to = SceneB, + current = { currentScene }, + progress = { progress } + ) + ) + assertThat(state.isTransitioning()).isTrue() + + // Ignore the request if we are close to a scene that is not the current scene + assertThat(state.snapToIdleIfClose(threshold = 0.1f)).isFalse() + assertThat(state.isTransitioning()).isTrue() + + progress = 1f + currentScene = SceneA + assertThat(state.snapToIdleIfClose(threshold = 0.1f)).isFalse() + assertThat(state.isTransitioning()).isTrue() + } + + @Test fun linkedTransition_fuzzyLinksAreMatchedAndStarted() { val (parentState, childState) = setupLinkedStates(SceneC, SceneA, null, null, null, SceneD) val childTransition = transition(SceneA, SceneB) @@ -407,7 +414,7 @@ class SceneTransitionLayoutStateTest { assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() - childState.finishTransition(childTransition, SceneB) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneB)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneD)) } @@ -417,13 +424,13 @@ class SceneTransitionLayoutStateTest { val (parentState, childState) = setupLinkedStates(SceneC, SceneA, SceneA, null, null, SceneD) - val childTransition = transition(SceneA, SceneB) + val childTransition = transition(SceneA, SceneB, current = { SceneA }) childState.startTransition(childTransition) assertThat(childState.isTransitioning(SceneA, SceneB)).isTrue() assertThat(parentState.isTransitioning(SceneC, SceneD)).isTrue() - childState.finishTransition(childTransition, SceneA) + childState.finishTransition(childTransition) assertThat(childState.transitionState).isEqualTo(TransitionState.Idle(SceneA)) assertThat(parentState.transitionState).isEqualTo(TransitionState.Idle(SceneC)) } @@ -595,12 +602,12 @@ class SceneTransitionLayoutStateTest { // Mark bToC as finished. The list of current transitions does not change because aToB is // still not marked as finished. - state.finishTransition(bToC, idleScene = bToC.currentScene) - assertThat(state.finishedTransitions).containsExactly(bToC, bToC.currentScene) + state.finishTransition(bToC) + assertThat(state.finishedTransitions).containsExactly(bToC) assertThat(state.currentTransitions).containsExactly(aToB, bToC, cToA).inOrder() // Mark aToB as finished. This will remove both aToB and bToC from the list of transitions. - state.finishTransition(aToB, idleScene = aToB.currentScene) + state.finishTransition(aToB) assertThat(state.finishedTransitions).isEmpty() assertThat(state.currentTransitions).containsExactly(cToA).inOrder() } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt index 91bd7e1800cd..e4e410828d0a 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.test.TestScope fun transition( from: SceneKey, to: SceneKey, - current: () -> SceneKey = { from }, + current: () -> SceneKey = { to }, progress: () -> Float = { 0f }, progressVelocity: () -> Float = { 0f }, previewProgress: () -> Float = { 0f }, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt index c9fa671ad34f..deef65218c4b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt @@ -22,14 +22,14 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel -import com.android.systemui.bouncer.domain.interactor.bouncerInteractor -import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -39,17 +39,16 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val bouncerInteractor by lazy { kosmos.bouncerInteractor } - private val underTest by lazy { - PinBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, + private val underTest = + kosmos.pinBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true), - simBouncerInteractor = kosmos.simBouncerInteractor, - authenticationMethod = AuthenticationMethodModel.Pin, onIntentionalUserInput = {}, + authenticationMethod = AuthenticationMethodModel.Pin, ) + + @Before + fun setUp() { + underTest.activateIn(testScope) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt index 4f5d0e58ce01..b83ab7ef0c1b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt @@ -52,6 +52,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthentication import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository @@ -87,6 +88,7 @@ class BouncerMessageViewModelTest : SysuiTestCase() { intArrayOf(ignoreHelpMessageId) ) underTest = kosmos.bouncerMessageViewModel + underTest.activateIn(testScope) overrideResource(R.string.kg_trust_agent_disabled, "Trust agent is unavailable") kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt new file mode 100644 index 000000000000..a86a0c022c21 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bouncer.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn +import com.android.systemui.scene.domain.startable.sceneContainerStartable +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.shared.model.fakeSceneDataSource +import com.android.systemui.testKosmos +import com.android.systemui.truth.containsEntriesExactly +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +@EnableSceneContainer +class BouncerSceneActionsViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private lateinit var underTest: BouncerSceneActionsViewModel + + @Before + fun setUp() { + kosmos.sceneContainerStartable.start() + underTest = kosmos.bouncerSceneActionsViewModel + underTest.activateIn(testScope) + } + + @Test + fun actions() = + testScope.runTest { + val actions by collectLastValue(underTest.actions) + kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings) + runCurrent() + + kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer) + runCurrent() + + assertThat(actions) + .containsEntriesExactly( + Back to UserActionResult(Scenes.QuickSettings), + Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings), + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModelTest.kt index ccddc9c7120f..9bddcd254556 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModelTest.kt @@ -18,10 +18,6 @@ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.compose.animation.scene.Back -import com.android.compose.animation.scene.Swipe -import com.android.compose.animation.scene.SwipeDirection -import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository @@ -38,11 +34,9 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.scene.domain.startable.sceneContainerStartable -import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos -import com.android.systemui.truth.containsEntriesExactly import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -62,17 +56,18 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableSceneContainer -class BouncerViewModelTest : SysuiTestCase() { +class BouncerSceneContentViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private lateinit var underTest: BouncerViewModel + private lateinit var underTest: BouncerSceneContentViewModel @Before fun setUp() { kosmos.sceneContainerStartable.start() - underTest = kosmos.bouncerViewModel + underTest = kosmos.bouncerSceneContentViewModel + underTest.activateIn(testScope) } @Test @@ -201,23 +196,6 @@ class BouncerViewModelTest : SysuiTestCase() { assertThat(isFoldSplitRequired).isTrue() } - @Test - fun destinationScenes() = - testScope.runTest { - val destinationScenes by collectLastValue(underTest.destinationScenes) - kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings) - runCurrent() - - kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer) - runCurrent() - - assertThat(destinationScenes) - .containsEntriesExactly( - Back to UserActionResult(Scenes.QuickSettings), - Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings), - ) - } - private fun authMethodsToTest(): List<AuthenticationMethodModel> { return listOf(None, Pin, Password, Pattern, Sim) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt index a09189efa41b..492543f215b7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.inputmethod.data.model.InputMethodModel import com.android.systemui.inputmethod.data.repository.fakeInputMethodRepository import com.android.systemui.inputmethod.domain.interactor.inputMethodInteractor import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes @@ -44,7 +45,6 @@ import java.util.UUID import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent @@ -68,12 +68,8 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { private val isInputEnabled = MutableStateFlow(true) private val underTest = - PasswordBouncerViewModel( - viewModelScope = testScope.backgroundScope, - isInputEnabled = isInputEnabled.asStateFlow(), - interactor = bouncerInteractor, - inputMethodInteractor = inputMethodInteractor, - selectedUserInteractor = selectedUserInteractor, + kosmos.passwordBouncerViewModelFactory.create( + isInputEnabled = isInputEnabled, onIntentionalUserInput = {}, ) @@ -81,6 +77,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { fun setUp() { overrideResource(R.string.keyguard_enter_your_password, ENTER_YOUR_PASSWORD) overrideResource(R.string.kg_wrong_password, WRONG_PASSWORD) + underTest.activateIn(testScope) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index 14d36343041d..7c773a902367 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt @@ -26,9 +26,9 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate as Point -import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes @@ -54,17 +54,12 @@ class PatternBouncerViewModelTest : SysuiTestCase() { private val testScope = kosmos.testScope private val authenticationInteractor by lazy { kosmos.authenticationInteractor } private val sceneInteractor by lazy { kosmos.sceneInteractor } - private val bouncerInteractor by lazy { kosmos.bouncerInteractor } - private val bouncerViewModel by lazy { kosmos.bouncerViewModel } - private val underTest by lazy { - PatternBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, + private val bouncerViewModel by lazy { kosmos.bouncerSceneContentViewModel } + private val underTest = + kosmos.patternBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true).asStateFlow(), onIntentionalUserInput = {}, ) - } private val containerSize = 90 // px private val dotSize = 30 // px @@ -73,6 +68,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { fun setUp() { overrideResource(R.string.keyguard_enter_your_pattern, ENTER_YOUR_PATTERN) overrideResource(R.string.kg_wrong_pattern, WRONG_PATTERN) + underTest.activateIn(testScope) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 89bafb952211..8d82e972bdaa 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -31,10 +31,9 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.data.repository.fakeSimBouncerRepository -import com.android.systemui.bouncer.domain.interactor.bouncerInteractor -import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes @@ -44,7 +43,6 @@ import kotlin.random.Random import kotlin.random.nextInt import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent @@ -62,24 +60,18 @@ class PinBouncerViewModelTest : SysuiTestCase() { private val testScope = kosmos.testScope private val sceneInteractor by lazy { kosmos.sceneInteractor } private val authenticationInteractor by lazy { kosmos.authenticationInteractor } - private val bouncerInteractor by lazy { kosmos.bouncerInteractor } - private lateinit var underTest: PinBouncerViewModel + private val underTest = + kosmos.pinBouncerViewModelFactory.create( + isInputEnabled = MutableStateFlow(true), + onIntentionalUserInput = {}, + authenticationMethod = AuthenticationMethodModel.Pin, + ) @Before fun setUp() { - underTest = - PinBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, - isInputEnabled = MutableStateFlow(true).asStateFlow(), - simBouncerInteractor = kosmos.simBouncerInteractor, - authenticationMethod = AuthenticationMethodModel.Pin, - onIntentionalUserInput = {}, - ) - overrideResource(R.string.keyguard_enter_your_pin, ENTER_YOUR_PIN) overrideResource(R.string.kg_wrong_pin, WRONG_PIN) + underTest.activateIn(testScope) } @Test @@ -96,14 +88,10 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun simBouncerViewModel_simAreaIsVisible() = testScope.runTest { val underTest = - PinBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, - isInputEnabled = MutableStateFlow(true).asStateFlow(), - simBouncerInteractor = kosmos.simBouncerInteractor, - authenticationMethod = AuthenticationMethodModel.Sim, + kosmos.pinBouncerViewModelFactory.create( + isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, + authenticationMethod = AuthenticationMethodModel.Sim, ) assertThat(underTest.isSimAreaVisible).isTrue() @@ -125,14 +113,10 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun simBouncerViewModel_autoConfirmEnabled_hintedPinLengthIsNull() = testScope.runTest { val underTest = - PinBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, - isInputEnabled = MutableStateFlow(true).asStateFlow(), - simBouncerInteractor = kosmos.simBouncerInteractor, - authenticationMethod = AuthenticationMethodModel.Sim, + kosmos.pinBouncerViewModelFactory.create( + isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, + authenticationMethod = AuthenticationMethodModel.Pin, ) kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true) val hintedPinLength by collectLastValue(underTest.hintedPinLength) @@ -355,6 +339,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { AuthenticationMethodModel.Pin ) kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true) + runCurrent() underTest.onPinButtonClicked(1) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryTest.kt new file mode 100644 index 000000000000..81cdce430d38 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryTest.kt @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data.repository + +import android.app.usage.UsageEvents +import android.app.usage.UsageEventsQuery +import android.app.usage.UsageStatsManager +import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.usagestats.data.model.UsageStatsQuery +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel.Lifecycle +import com.android.systemui.kosmos.backgroundCoroutineContext +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.mock + +@SmallTest +@RunWith(AndroidJUnit4::class) +class UsageStatsRepositoryTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val fakeUsageStatsManager = FakeUsageStatsManager() + + private val usageStatsManager = + mock<UsageStatsManager> { + on { queryEvents(any()) } doAnswer + { inv -> + val query = inv.getArgument(0) as UsageEventsQuery + fakeUsageStatsManager.queryEvents(query) + } + } + + private val underTest by lazy { + UsageStatsRepositoryImpl( + bgContext = kosmos.backgroundCoroutineContext, + usageStatsManager = usageStatsManager, + ) + } + + @Test + fun testQueryWithBeginAndEndTime() = + testScope.runTest { + with(fakeUsageStatsManager) { + // This event is outside the queried time, and therefore should + // not be returned. + addEvent( + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 5, + instanceId = 1, + ) + addEvent( + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + type = UsageEvents.Event.ACTIVITY_STOPPED, + timestamp = 20, + instanceId = 2, + ) + // This event is outside the queried time, and therefore should + // not be returned. + addEvent( + type = UsageEvents.Event.ACTIVITY_DESTROYED, + timestamp = 50, + instanceId = 2, + ) + } + + assertThat( + underTest.queryActivityEvents( + UsageStatsQuery(MAIN_USER, startTime = 10, endTime = 50), + ), + ) + .containsExactly( + ActivityEventModel( + instanceId = 1, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.PAUSED, + timestamp = 10, + ), + ActivityEventModel( + instanceId = 2, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.STOPPED, + timestamp = 20, + ), + ) + } + + @Test + fun testQueryForDifferentUsers() = + testScope.runTest { + with(fakeUsageStatsManager) { + addEvent( + user = MAIN_USER, + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + user = SECONDARY_USER, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 11, + instanceId = 2, + ) + } + + assertThat( + underTest.queryActivityEvents( + UsageStatsQuery(MAIN_USER, startTime = 10, endTime = 15), + ), + ) + .containsExactly( + ActivityEventModel( + instanceId = 1, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.PAUSED, + timestamp = 10, + ), + ) + } + + @Test + fun testQueryForSpecificPackages() = + testScope.runTest { + with(fakeUsageStatsManager) { + addEvent( + packageName = DEFAULT_PACKAGE, + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + packageName = OTHER_PACKAGE, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 11, + instanceId = 2, + ) + } + + assertThat( + underTest.queryActivityEvents( + UsageStatsQuery( + MAIN_USER, + startTime = 10, + endTime = 10000, + packageNames = listOf(OTHER_PACKAGE), + ), + ), + ) + .containsExactly( + ActivityEventModel( + instanceId = 2, + packageName = OTHER_PACKAGE, + lifecycle = Lifecycle.RESUMED, + timestamp = 11, + ), + ) + } + + @Test + fun testNonActivityEvent() = + testScope.runTest { + with(fakeUsageStatsManager) { + addEvent( + type = UsageEvents.Event.CHOOSER_ACTION, + timestamp = 10, + instanceId = 1, + ) + } + + assertThat( + underTest.queryActivityEvents( + UsageStatsQuery( + MAIN_USER, + startTime = 1, + endTime = 20, + ), + ), + ) + .isEmpty() + } + + private class FakeUsageStatsManager() { + private val events = mutableMapOf<Int, MutableList<UsageEvents.Event>>() + + fun queryEvents(query: UsageEventsQuery): UsageEvents { + val results = + events + .getOrDefault(query.userId, emptyList()) + .filter { event -> + query.packageNames.isEmpty() || + query.packageNames.contains(event.packageName) + } + .filter { event -> + event.timeStamp in query.beginTimeMillis until query.endTimeMillis + } + .filter { event -> + query.eventTypes.isEmpty() || query.eventTypes.contains(event.eventType) + } + return UsageEvents(results, emptyArray()) + } + + fun addEvent( + type: Int, + instanceId: Int = 0, + user: UserHandle = MAIN_USER, + packageName: String = DEFAULT_PACKAGE, + timestamp: Long, + ) { + events + .getOrPut(user.identifier) { mutableListOf() } + .add( + UsageEvents.Event(type, timestamp).apply { + mPackage = packageName + mInstanceId = instanceId + } + ) + } + } + + private companion object { + const val DEFAULT_PACKAGE = "pkg.default" + const val OTHER_PACKAGE = "pkg.other" + val MAIN_USER: UserHandle = UserHandle.of(0) + val SECONDARY_USER: UserHandle = UserHandle.of(1) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorTest.kt new file mode 100644 index 000000000000..af455880bc25 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorTest.kt @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.domain.interactor + +import android.annotation.CurrentTimeMillisLong +import android.app.usage.UsageEvents +import android.content.pm.UserInfo +import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.usagestats.data.repository.fakeUsageStatsRepository +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel.Lifecycle +import com.android.systemui.kosmos.testScope +import com.android.systemui.settings.fakeUserTracker +import com.android.systemui.testKosmos +import com.android.systemui.util.time.fakeSystemClock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class UsageStatsInteractorTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val userTracker = kosmos.fakeUserTracker + private val systemClock = kosmos.fakeSystemClock + private val repository = kosmos.fakeUsageStatsRepository + + private val underTest = kosmos.usageStatsInteractor + + @Before + fun setUp() { + userTracker.set(listOf(MAIN_USER, SECONDARY_USER), 0) + } + + @Test + fun testQueryWithBeginAndEndTime() = + testScope.runTest { + // This event is outside the queried time, and therefore should + // not be returned. + addEvent( + instanceId = 1, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 5, + ) + addEvent( + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + type = UsageEvents.Event.ACTIVITY_STOPPED, + timestamp = 20, + instanceId = 2, + ) + // This event is outside the queried time, and therefore should + // not be returned. + addEvent( + type = UsageEvents.Event.ACTIVITY_DESTROYED, + timestamp = 50, + instanceId = 2, + ) + + assertThat(underTest.queryActivityEvents(startTime = 10, endTime = 50)) + .containsExactly( + ActivityEventModel( + instanceId = 1, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.PAUSED, + timestamp = 10, + ), + ActivityEventModel( + instanceId = 2, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.STOPPED, + timestamp = 20, + ), + ) + } + + @Test + fun testQueryForDifferentUsers() = + testScope.runTest { + addEvent( + user = MAIN_USER.userHandle, + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + user = SECONDARY_USER.userHandle, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 11, + instanceId = 2, + ) + + assertThat(underTest.queryActivityEvents(startTime = 10, endTime = 15)) + .containsExactly( + ActivityEventModel( + instanceId = 1, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.PAUSED, + timestamp = 10, + ), + ) + } + + @Test + fun testQueryWithUserSpecified() = + testScope.runTest { + addEvent( + user = MAIN_USER.userHandle, + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + user = SECONDARY_USER.userHandle, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 11, + instanceId = 2, + ) + + assertThat( + underTest.queryActivityEvents( + startTime = 10, + endTime = 15, + userHandle = SECONDARY_USER.userHandle, + ), + ) + .containsExactly( + ActivityEventModel( + instanceId = 2, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.RESUMED, + timestamp = 11, + ), + ) + } + + @Test + fun testQueryForSpecificPackages() = + testScope.runTest { + addEvent( + packageName = DEFAULT_PACKAGE, + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + packageName = OTHER_PACKAGE, + type = UsageEvents.Event.ACTIVITY_RESUMED, + timestamp = 11, + instanceId = 2, + ) + + assertThat( + underTest.queryActivityEvents( + startTime = 10, + endTime = 10000, + packageNames = listOf(OTHER_PACKAGE), + ), + ) + .containsExactly( + ActivityEventModel( + instanceId = 2, + packageName = OTHER_PACKAGE, + lifecycle = Lifecycle.RESUMED, + timestamp = 11, + ), + ) + } + + @Test + fun testNonActivityEvent() = + testScope.runTest { + addEvent( + type = UsageEvents.Event.CHOOSER_ACTION, + timestamp = 10, + instanceId = 1, + ) + + assertThat(underTest.queryActivityEvents(startTime = 1, endTime = 20)).isEmpty() + } + + @Test + fun testNoEndTimeSpecified() = + testScope.runTest { + systemClock.setCurrentTimeMillis(30) + + addEvent( + type = UsageEvents.Event.ACTIVITY_PAUSED, + timestamp = 10, + instanceId = 1, + ) + addEvent( + type = UsageEvents.Event.ACTIVITY_STOPPED, + timestamp = 20, + instanceId = 2, + ) + // This event is outside the queried time, and therefore should + // not be returned. + addEvent( + type = UsageEvents.Event.ACTIVITY_DESTROYED, + timestamp = 50, + instanceId = 2, + ) + + assertThat(underTest.queryActivityEvents(startTime = 1)) + .containsExactly( + ActivityEventModel( + instanceId = 1, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.PAUSED, + timestamp = 10, + ), + ActivityEventModel( + instanceId = 2, + packageName = DEFAULT_PACKAGE, + lifecycle = Lifecycle.STOPPED, + timestamp = 20, + ), + ) + } + + private fun addEvent( + instanceId: Int, + user: UserHandle = MAIN_USER.userHandle, + packageName: String = DEFAULT_PACKAGE, + @UsageEvents.Event.EventType type: Int, + @CurrentTimeMillisLong timestamp: Long, + ) { + repository.addEvent( + instanceId = instanceId, + user = user, + packageName = packageName, + type = type, + timestamp = timestamp, + ) + } + + private companion object { + const val DEFAULT_PACKAGE = "pkg.default" + const val OTHER_PACKAGE = "pkg.other" + val MAIN_USER: UserInfo = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + val SECONDARY_USER: UserInfo = UserInfo(10, "secondary", 0) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index 9ccf99b301b1..70529cc762e0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -112,7 +112,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) communalSceneInteractor.setEditModeState(EditModeState.STARTING) @@ -133,7 +133,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) communalSceneInteractor.setIsLaunchingWidget(true) @@ -154,7 +154,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) communalSceneInteractor.setIsLaunchingWidget(false) @@ -174,7 +174,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) communalInteractor.setEditModeOpen(true) @@ -213,7 +213,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(false) val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) updateDocked(true) @@ -233,7 +233,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(true) val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) updateDocked(true) @@ -270,7 +270,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -292,7 +292,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") assertThat(scene).isEqualTo(CommunalScenes.Communal) fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -320,7 +320,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun dockingOnLockscreen_forcesCommunal() = with(kosmos) { testScope.runTest { - communalSceneInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene(CommunalScenes.Blank, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) // device is docked while on the lockscreen @@ -342,7 +342,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun dockingOnLockscreen_doesNotForceCommunalIfDreamStarts() = with(kosmos) { testScope.runTest { - communalSceneInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene(CommunalScenes.Blank, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) // device is docked while on the lockscreen @@ -374,7 +374,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -391,7 +391,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is not dreaming and on communal. updateDreaming(false) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") // Scene stays as Communal advanceTimeBy(SCREEN_TIMEOUT.milliseconds) @@ -406,7 +406,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -429,7 +429,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is on communal, but not dreaming. updateDreaming(false) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -450,7 +450,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { // Device is on communal. - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") // Device stays on the hub after the timeout since we're not dreaming. advanceTimeBy(SCREEN_TIMEOUT.milliseconds * 2) @@ -471,7 +471,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -500,7 +500,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { // Device is dreaming and on communal. updateDreaming(true) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -520,7 +520,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene(CommunalScenes.Blank, "test") assertThat(scene).isEqualTo(CommunalScenes.Blank) fakeKeyguardTransitionRepository.sendTransitionSteps( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalMediaRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalMediaRepositoryImplTest.kt index dd280223f203..dd5ad17fd875 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalMediaRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalMediaRepositoryImplTest.kt @@ -67,7 +67,7 @@ class CommunalMediaRepositoryImplTest : SysuiTestCase() { testScope.runTest { val mediaModel = collectLastValue(underTest.mediaModel) runCurrent() - assertThat(mediaModel()?.hasActiveMediaOrRecommendation).isFalse() + assertThat(mediaModel()?.hasAnyMediaOrRecommendation).isFalse() } @Test @@ -81,16 +81,16 @@ class CommunalMediaRepositoryImplTest : SysuiTestCase() { // Initial value is false. val mediaModel = collectLastValue(underTest.mediaModel) runCurrent() - assertThat(mediaModel()?.hasActiveMediaOrRecommendation).isFalse() + assertThat(mediaModel()?.hasAnyMediaOrRecommendation).isFalse() // Change to media available and notify the listener. - whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true) + whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(true) whenever(mediaData.createdTimestampMillis).thenReturn(1234L) mediaDataListenerCaptor.firstValue.onMediaDataLoaded("key", null, mediaData) runCurrent() // Media active now returns true. - assertThat(mediaModel()?.hasActiveMediaOrRecommendation).isTrue() + assertThat(mediaModel()?.hasAnyMediaOrRecommendation).isTrue() assertThat(mediaModel()?.createdTimestampMillis).isEqualTo(1234L) } @@ -103,20 +103,20 @@ class CommunalMediaRepositoryImplTest : SysuiTestCase() { verify(mediaDataManager).addListener(mediaDataListenerCaptor.capture()) // Change to media available and notify the listener. - whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true) + whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(true) mediaDataListenerCaptor.firstValue.onMediaDataLoaded("key", null, mediaData) runCurrent() // Media active now returns true. val mediaModel = collectLastValue(underTest.mediaModel) - assertThat(mediaModel()?.hasActiveMediaOrRecommendation).isTrue() + assertThat(mediaModel()?.hasAnyMediaOrRecommendation).isTrue() // Change to media unavailable and notify the listener. - whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(false) + whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(false) mediaDataListenerCaptor.firstValue.onMediaDataRemoved("key", false) runCurrent() // Media active now returns false. - assertThat(mediaModel()?.hasActiveMediaOrRecommendation).isFalse() + assertThat(mediaModel()?.hasAnyMediaOrRecommendation).isFalse() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index e57a4cbc230e..864795b062be 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -482,7 +482,7 @@ class CommunalInteractorTest : SysuiTestCase() { testScope.runTest { val targetScene = CommunalScenes.Communal - underTest.changeScene(targetScene) + underTest.changeScene(targetScene, "test") val desiredScene = collectLastValue(communalRepository.currentScene) runCurrent() @@ -635,7 +635,7 @@ class CommunalInteractorTest : SysuiTestCase() { runCurrent() assertThat(isCommunalShowing()).isEqualTo(false) - underTest.changeScene(CommunalScenes.Communal) + underTest.changeScene(CommunalScenes.Communal, "test") isCommunalShowing = collectLastValue(underTest.isCommunalShowing) runCurrent() @@ -659,12 +659,12 @@ class CommunalInteractorTest : SysuiTestCase() { assertThat(isCommunalShowing).isFalse() // Verify scene changes (without the flag) to communal sets the value to true - underTest.changeScene(CommunalScenes.Communal) + underTest.changeScene(CommunalScenes.Communal, "test") runCurrent() assertThat(isCommunalShowing).isTrue() // Verify scene changes (without the flag) to blank sets the value back to false - underTest.changeScene(CommunalScenes.Blank) + underTest.changeScene(CommunalScenes.Blank, "test") runCurrent() assertThat(isCommunalShowing).isFalse() } @@ -679,7 +679,7 @@ class CommunalInteractorTest : SysuiTestCase() { assertThat(isCommunalShowing).isFalse() // Verify scene changes without the flag doesn't have any impact - underTest.changeScene(CommunalScenes.Communal) + underTest.changeScene(CommunalScenes.Communal, "test") runCurrent() assertThat(isCommunalShowing).isFalse() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt index 43293c7a50ca..ed7e9107240e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt @@ -53,7 +53,7 @@ class CommunalSceneInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) - underTest.changeScene(CommunalScenes.Communal) + underTest.changeScene(CommunalScenes.Communal, "test") assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } @@ -63,7 +63,7 @@ class CommunalSceneInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(underTest.currentScene) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) - underTest.snapToScene(CommunalScenes.Communal) + underTest.snapToScene(CommunalScenes.Communal, "test") assertThat(currentScene).isEqualTo(CommunalScenes.Communal) } @@ -75,6 +75,7 @@ class CommunalSceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(CommunalScenes.Blank) underTest.snapToScene( CommunalScenes.Communal, + "test", ActivityTransitionAnimator.TIMINGS.totalDuration ) assertThat(currentScene).isEqualTo(CommunalScenes.Blank) @@ -86,7 +87,7 @@ class CommunalSceneInteractorTest : SysuiTestCase() { fun changeSceneForActivityStartOnDismissKeyguard() = testScope.runTest { val currentScene by collectLastValue(underTest.currentScene) - underTest.snapToScene(CommunalScenes.Communal) + underTest.snapToScene(CommunalScenes.Communal, "test") assertThat(currentScene).isEqualTo(CommunalScenes.Communal) underTest.changeSceneForActivityStartOnDismissKeyguard() @@ -97,7 +98,7 @@ class CommunalSceneInteractorTest : SysuiTestCase() { fun changeSceneForActivityStartOnDismissKeyguard_willNotChangeScene_forEditModeActivity() = testScope.runTest { val currentScene by collectLastValue(underTest.currentScene) - underTest.snapToScene(CommunalScenes.Communal) + underTest.snapToScene(CommunalScenes.Communal, "test") assertThat(currentScene).isEqualTo(CommunalScenes.Communal) underTest.setEditModeState(EditModeState.STARTING) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt index d6712f09cd4e..c5518b029bc1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt @@ -53,6 +53,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat +import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -78,6 +79,7 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { private val underTest by lazy { kosmos.communalSceneTransitionInteractor } private val keyguardTransitionRepository by lazy { kosmos.realKeyguardTransitionRepository } + private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository } private val ownerName = CommunalSceneTransitionInteractor::class.java.simpleName private val progress = MutableSharedFlow<Float>() @@ -789,4 +791,47 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { ) ) } + + /** Verifies that we correctly transition to GONE after keyguard goes away */ + @Test + fun transition_to_blank_after_unlock_should_go_to_gone() = + testScope.runTest { + keyguardRepository.setKeyguardShowing(true) + sceneTransitions.value = Idle(CommunalScenes.Communal) + + val currentStep by collectLastValue(keyguardTransitionRepository.transitions) + + assertThat(currentStep) + .isEqualTo( + TransitionStep( + from = LOCKSCREEN, + to = GLANCEABLE_HUB, + transitionState = FINISHED, + value = 1f, + ownerName = ownerName, + ) + ) + + // Keyguard starts exiting after a while, then fully exits after some time. + advanceTimeBy(1.seconds) + keyguardRepository.setKeyguardGoingAway(true) + advanceTimeBy(2.seconds) + keyguardRepository.setKeyguardGoingAway(false) + keyguardRepository.setKeyguardShowing(false) + runCurrent() + + // We snap to the blank scene as a result of keyguard going away. + sceneTransitions.value = Idle(CommunalScenes.Blank) + + assertThat(currentStep) + .isEqualTo( + TransitionStep( + from = GLANCEABLE_HUB, + to = GONE, + transitionState = FINISHED, + value = 1f, + ownerName = ownerName, + ) + ) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt index 3a23e14e2777..7e28e19d0ee0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt @@ -158,7 +158,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { kosmos.setCommunalAvailable(true) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) - communalInteractor.changeScene(CommunalScenes.Blank) + communalInteractor.changeScene(CommunalScenes.Blank, "test") assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_NOT_STARTED) } @@ -171,7 +171,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED) - communalInteractor.changeScene(CommunalScenes.Blank) + communalInteractor.changeScene(CommunalScenes.Blank, "test") assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } @@ -184,13 +184,13 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { goToCommunal() communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - communalInteractor.changeScene(CommunalScenes.Blank) + communalInteractor.changeScene(CommunalScenes.Blank, "test") assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } private suspend fun goToCommunal() { kosmos.setCommunalAvailable(true) - communalInteractor.changeScene(CommunalScenes.Communal) + communalInteractor.changeScene(CommunalScenes.Communal, "test") } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt new file mode 100644 index 000000000000..b3ffc7159f7c --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorTest.kt @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import android.app.ActivityManager.RunningTaskInfo +import android.app.usage.UsageEvents +import android.content.pm.UserInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.usagestats.data.repository.fakeUsageStatsRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.kosmos.testScope +import com.android.systemui.plugins.activityStarter +import com.android.systemui.settings.fakeUserTracker +import com.android.systemui.shared.system.taskStackChangeListeners +import com.android.systemui.testKosmos +import com.android.systemui.util.time.fakeSystemClock +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.currentTime +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.times +import org.mockito.kotlin.verify + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class WidgetTrampolineInteractorTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val activityStarter = kosmos.activityStarter + private val usageStatsRepository = kosmos.fakeUsageStatsRepository + private val taskStackChangeListeners = kosmos.taskStackChangeListeners + private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + private val userTracker = kosmos.fakeUserTracker + private val systemClock = kosmos.fakeSystemClock + + private val underTest = kosmos.widgetTrampolineInteractor + + @Before + fun setUp() { + userTracker.set(listOf(MAIN_USER), 0) + systemClock.setCurrentTimeMillis(testScope.currentTime) + } + + @Test + fun testNewTaskStartsWhileOnHub_triggersUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + moveTaskToFront() + + verify(activityStarter).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testNewTaskStartsAfterExitingHub_doesNotTriggerUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + transition(from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN) + moveTaskToFront() + + verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testNewTaskStartsAfterTimeout_doesNotTriggerUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + advanceTime(2.seconds) + moveTaskToFront() + + verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testActivityResumedWhileOnHub_triggersUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED) + advanceTime(1.seconds) + + verify(activityStarter).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testActivityResumedAfterExitingHub_doesNotTriggerUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + transition(from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN) + addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED) + advanceTime(1.seconds) + + verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testActivityDestroyed_doesNotTriggerUnlock() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + addActivityEvent(UsageEvents.Event.ACTIVITY_DESTROYED) + advanceTime(1.seconds) + + verify(activityStarter, never()).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + @Test + fun testMultipleActivityEvents_triggersUnlockOnlyOnce() = + testScope.runTest { + transition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GLANCEABLE_HUB) + backgroundScope.launch { underTest.waitForActivityStartAndDismissKeyguard() } + runCurrent() + + addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED) + advanceTime(10.milliseconds) + addActivityEvent(UsageEvents.Event.ACTIVITY_RESUMED) + advanceTime(1.seconds) + + verify(activityStarter, times(1)).dismissKeyguardThenExecute(any(), anyOrNull(), any()) + } + + private fun TestScope.advanceTime(duration: Duration) { + systemClock.advanceTime(duration.inWholeMilliseconds) + advanceTimeBy(duration) + } + + private fun TestScope.addActivityEvent(type: Int) { + usageStatsRepository.addEvent( + instanceId = 1, + user = MAIN_USER.userHandle, + packageName = "pkg.test", + timestamp = systemClock.currentTimeMillis(), + type = type, + ) + runCurrent() + } + + private fun TestScope.moveTaskToFront() { + taskStackChangeListeners.listenerImpl.onTaskMovedToFront(mock<RunningTaskInfo>()) + runCurrent() + } + + private suspend fun TestScope.transition(from: KeyguardState, to: KeyguardState) { + keyguardTransitionRepository.sendTransitionSteps( + listOf( + TransitionStep( + from = from, + to = to, + value = 0.1f, + transitionState = TransitionState.STARTED, + ownerName = "test", + ), + TransitionStep( + from = from, + to = to, + value = 1f, + transitionState = TransitionState.FINISHED, + ownerName = "test", + ), + ), + testScope + ) + runCurrent() + } + + private companion object { + val MAIN_USER: UserInfo = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt index e36fd75445e2..a052b078167d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt @@ -76,7 +76,7 @@ class CommunalTransitionAnimatorControllerTest : SysuiTestCase() { val launching by collectLastValue(communalSceneInteractor.isLaunchingWidget) val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") Truth.assertThat(scene).isEqualTo(CommunalScenes.Communal) communalSceneInteractor.setIsLaunchingWidget(true) assertTrue(launching!!) @@ -103,7 +103,7 @@ class CommunalTransitionAnimatorControllerTest : SysuiTestCase() { val launching by collectLastValue(communalSceneInteractor.isLaunchingWidget) val scene by collectLastValue(communalSceneInteractor.currentScene) - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") Truth.assertThat(scene).isEqualTo(CommunalScenes.Communal) communalSceneInteractor.setIsLaunchingWidget(true) assertTrue(launching!!) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/EditWidgetsActivityControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/EditWidgetsActivityControllerTest.kt deleted file mode 100644 index 50fdb31b0414..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/EditWidgetsActivityControllerTest.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.communal.widgets - -import android.app.Activity -import android.app.Application.ActivityLifecycleCallbacks -import android.os.Bundle -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import kotlinx.coroutines.ExperimentalCoroutinesApi -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.kotlin.argumentCaptor -import org.mockito.kotlin.clearInvocations -import org.mockito.kotlin.mock -import org.mockito.kotlin.never -import org.mockito.kotlin.verify - -@ExperimentalCoroutinesApi -@SmallTest -@RunWith(AndroidJUnit4::class) -class EditWidgetsActivityControllerTest : SysuiTestCase() { - @Test - fun activityLifecycle_stoppedWhenNotWaitingForResult() { - val activity = mock<Activity>() - val controller = EditWidgetsActivity.ActivityController(activity) - - val callbackCapture = argumentCaptor<ActivityLifecycleCallbacks>() - verify(activity).registerActivityLifecycleCallbacks(callbackCapture.capture()) - - callbackCapture.lastValue.onActivityStopped(activity) - - verify(activity).finish() - } - - @Test - fun activityLifecycle_notStoppedWhenNotWaitingForResult() { - val activity = mock<Activity>() - val controller = EditWidgetsActivity.ActivityController(activity) - - val callbackCapture = argumentCaptor<ActivityLifecycleCallbacks>() - verify(activity).registerActivityLifecycleCallbacks(callbackCapture.capture()) - - controller.onWaitingForResult(true) - callbackCapture.lastValue.onActivityStopped(activity) - - verify(activity, never()).finish() - } - - @Test - fun activityLifecycle_stoppedAfterResultReturned() { - val activity = mock<Activity>() - val controller = EditWidgetsActivity.ActivityController(activity) - - val callbackCapture = argumentCaptor<ActivityLifecycleCallbacks>() - verify(activity).registerActivityLifecycleCallbacks(callbackCapture.capture()) - - controller.onWaitingForResult(true) - controller.onWaitingForResult(false) - callbackCapture.lastValue.onActivityStopped(activity) - - verify(activity).finish() - } - - @Test - fun activityLifecycle_statePreservedThroughInstanceSave() { - val activity = mock<Activity>() - val bundle = Bundle(1) - - run { - val controller = EditWidgetsActivity.ActivityController(activity) - val callbackCapture = argumentCaptor<ActivityLifecycleCallbacks>() - verify(activity).registerActivityLifecycleCallbacks(callbackCapture.capture()) - - controller.onWaitingForResult(true) - callbackCapture.lastValue.onActivitySaveInstanceState(activity, bundle) - } - - clearInvocations(activity) - - run { - val controller = EditWidgetsActivity.ActivityController(activity) - val callbackCapture = argumentCaptor<ActivityLifecycleCallbacks>() - verify(activity).registerActivityLifecycleCallbacks(callbackCapture.capture()) - - callbackCapture.lastValue.onActivityCreated(activity, bundle) - callbackCapture.lastValue.onActivityStopped(activity) - - verify(activity, never()).finish() - } - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt index 023de52b2460..9c308a60d3f0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt @@ -25,13 +25,19 @@ import androidx.core.util.component1 import androidx.core.util.component2 import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.keyguard.keyguardUpdateMonitor import com.android.systemui.SysuiTestCase import com.android.systemui.communal.domain.interactor.communalSceneInteractor +import com.android.systemui.communal.domain.interactor.widgetTrampolineInteractor import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.backgroundCoroutineContext import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.plugins.ActivityStarter import com.android.systemui.testKosmos +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -39,12 +45,14 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.isNull import org.mockito.kotlin.mock import org.mockito.kotlin.refEq import org.mockito.kotlin.verify +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class WidgetInteractionHandlerTest : SysuiTestCase() { @@ -67,9 +75,13 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { with(kosmos) { underTest = WidgetInteractionHandler( + applicationScope = applicationCoroutineScope, + uiBackgroundContext = backgroundCoroutineContext, activityStarter = activityStarter, communalSceneInteractor = communalSceneInteractor, + keyguardUpdateMonitor = keyguardUpdateMonitor, logBuffer = logcatLogBuffer(), + widgetTrampolineInteractor = widgetTrampolineInteractor, ) } } @@ -91,16 +103,21 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { // Verify that we set the state correctly assertTrue(launching!!) // Verify that we pass in a non-null Communal animation controller + + val callbackCaptor = argumentCaptor<Runnable>() verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard( /* intent = */ eq(testIntent), /* dismissShade = */ eq(false), - /* intentSentUiThreadCallback = */ isNull(), + /* intentSentUiThreadCallback = */ callbackCaptor.capture(), /* animationController = */ any<CommunalTransitionAnimatorController>(), /* fillInIntent = */ refEq(fillInIntent), /* extraOptions = */ refEq(activityOptions.toBundle()), /* customMessage */ isNull(), ) + callbackCaptor.firstValue.run() + runCurrent() + verify(keyguardUpdateMonitor).awakenFromDream() } } } @@ -119,7 +136,7 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { .startPendingIntentMaybeDismissingKeyguard( /* intent = */ eq(testIntent), /* dismissShade = */ eq(false), - /* intentSentUiThreadCallback = */ isNull(), + /* intentSentUiThreadCallback = */ any(), /* animationController = */ isNull(), /* fillInIntent = */ refEq(fillInIntent), /* extraOptions = */ refEq(activityOptions.toBundle()), diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt index 7a86e57779b9..da82b5f4a1f7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt @@ -68,7 +68,6 @@ import com.android.systemui.navigationbar.gestural.domain.GestureInteractor import com.android.systemui.testKosmos import com.android.systemui.touch.TouchInsetManager import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -87,6 +86,7 @@ import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.isNull import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.spy @@ -669,7 +669,7 @@ class DreamOverlayServiceTest : SysuiTestCase() { runCurrent() verify(mDreamOverlayCallback).onRedirectWake(true) client.onWakeRequested() - verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), isNull()) + verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), any(), isNull()) verify(mUiEventLogger).log(CommunalUiEvent.DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt index 5dd6c228e014..f82beff11d8f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt @@ -51,6 +51,7 @@ class ContextualEducationRepositoryTest : SysuiTestCase() { } private val testUserId = 1111 + private val secondTestUserId = 1112 // For deleting any test files created after the test @get:Rule val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() @@ -73,12 +74,21 @@ class ContextualEducationRepositoryTest : SysuiTestCase() { assertThat(model?.signalCount).isEqualTo(1) // User is changed. - underTest.setUser(1112) + underTest.setUser(secondTestUserId) // Assert count is 0 after user is changed. assertThat(model?.signalCount).isEqualTo(0) } @Test + fun changeUserIdForNewUser() = + testScope.runTest { + val model by collectLastValue(underTest.readGestureEduModelFlow(BACK)) + assertThat(model?.userId).isEqualTo(testUserId) + underTest.setUser(secondTestUserId) + assertThat(model?.userId).isEqualTo(secondTestUserId) + } + + @Test fun dataChangedOnUpdate() = testScope.runTest { val newModel = @@ -88,6 +98,7 @@ class ContextualEducationRepositoryTest : SysuiTestCase() { lastShortcutTriggeredTime = kosmos.fakeEduClock.instant(), lastEducationTime = kosmos.fakeEduClock.instant(), usageSessionStartTime = kosmos.fakeEduClock.instant(), + userId = testUserId ) underTest.updateGestureEduModel(BACK) { newModel } val model by collectLastValue(underTest.readGestureEduModelFlow(BACK)) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt index 6867089473da..23f923a6fb09 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt @@ -109,7 +109,8 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { .isEqualTo( GestureEduModel( signalCount = 1, - usageSessionStartTime = secondSignalReceivedTime + usageSessionStartTime = secondSignalReceivedTime, + userId = 0 ) ) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt index 1f733472cbed..e075b7edda40 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt @@ -16,6 +16,8 @@ package com.android.systemui.education.domain.ui.view +import android.app.Notification +import android.app.NotificationManager import android.content.applicationContext import android.widget.Toast import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -30,27 +32,35 @@ import com.android.systemui.education.ui.view.ContextualEduUiCoordinator import com.android.systemui.education.ui.viewmodel.ContextualEduViewModel import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testScope +import com.android.systemui.res.R import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.junit.MockitoJUnit +import org.mockito.kotlin.any import org.mockito.kotlin.verify @SmallTest @RunWith(AndroidJUnit4::class) +@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) class ContextualEduUiCoordinatorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val interactor = kosmos.contextualEducationInteractor private lateinit var underTest: ContextualEduUiCoordinator @Mock private lateinit var toast: Toast - + @Mock private lateinit var notificationManager: NotificationManager @get:Rule val mockitoRule = MockitoJUnit.rule() + private var toastContent = "" @Before fun setUp() { @@ -60,23 +70,76 @@ class ContextualEduUiCoordinatorTest : SysuiTestCase() { kosmos.keyboardTouchpadEduInteractor ) underTest = - ContextualEduUiCoordinator(kosmos.applicationCoroutineScope, viewModel) { _ -> toast } + ContextualEduUiCoordinator( + kosmos.applicationCoroutineScope, + viewModel, + kosmos.applicationContext, + notificationManager + ) { content -> + toastContent = content + toast + } underTest.start() kosmos.keyboardTouchpadEduInteractor.start() } @Test - @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) fun showToastOnNewEdu() = testScope.runTest { triggerEducation(BACK) - runCurrent() verify(toast).show() } - private suspend fun triggerEducation(gestureType: GestureType) { + @Test + fun showNotificationOn2ndEdu() = + testScope.runTest { + triggerEducation(BACK) + triggerEducation(BACK) + verify(notificationManager).notifyAsUser(any(), anyInt(), any(), any()) + } + + @Test + fun verifyBackEduToastContent() = + testScope.runTest { + triggerEducation(BACK) + assertThat(toastContent).isEqualTo(context.getString(R.string.back_edu_toast_content)) + } + + @Test + fun verifyBackEduNotificationContent() = + testScope.runTest { + val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java) + triggerEducation(BACK) + triggerEducation(BACK) + verify(notificationManager) + .notifyAsUser(any(), anyInt(), notificationCaptor.capture(), any()) + verifyNotificationContent( + R.string.back_edu_notification_title, + R.string.back_edu_notification_content, + notificationCaptor.value + ) + } + + private fun verifyNotificationContent( + titleResId: Int, + contentResId: Int, + notification: Notification + ) { + val expectedContent = context.getString(contentResId) + val expectedTitle = context.getString(titleResId) + val actualContent = notification.getString(Notification.EXTRA_TEXT) + val actualTitle = notification.getString(Notification.EXTRA_TITLE) + assertThat(actualContent).isEqualTo(expectedContent) + assertThat(actualTitle).isEqualTo(expectedTitle) + } + + private fun Notification.getString(key: String): String = + this.extras?.getCharSequence(key).toString() + + private suspend fun TestScope.triggerEducation(gestureType: GestureType) { for (i in 1..KeyboardTouchpadEduInteractor.MAX_SIGNAL_COUNT) { interactor.incrementSignalCount(gestureType) } + runCurrent() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 8c1e8de315b1..9792c28d5023 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -845,7 +845,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GONE) // WHEN the glanceable hub is shown - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() assertThat(transitionRepository) @@ -1004,7 +1004,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun alternateBouncerToGlanceableHub() = testScope.runTest { // GIVEN the device is idle on the glanceable hub - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) @@ -1123,7 +1123,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun primaryBouncerToGlanceableHub() = testScope.runTest { // GIVEN the device is idle on the glanceable hub - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() // GIVEN a prior transition has run to PRIMARY_BOUNCER @@ -1157,7 +1157,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest advanceTimeBy(600L) // GIVEN the device is idle on the glanceable hub - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() // GIVEN a prior transition has run to PRIMARY_BOUNCER @@ -1971,7 +1971,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun glanceableHubToLockscreen_communalKtfRefactor() = testScope.runTest { // GIVEN a prior transition has run to GLANCEABLE_HUB - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) @@ -2035,7 +2035,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun glanceableHubToDozing_communalKtfRefactor() = testScope.runTest { // GIVEN a prior transition has run to GLANCEABLE_HUB - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) @@ -2136,7 +2136,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun glanceableHubToOccluded_communalKtfRefactor() = testScope.runTest { // GIVEN a prior transition has run to GLANCEABLE_HUB - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) @@ -2184,7 +2184,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun glanceableHubToGone_communalKtfRefactor() = testScope.runTest { // GIVEN a prior transition has run to GLANCEABLE_HUB - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) @@ -2265,7 +2265,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest advanceTimeBy(600L) // GIVEN a prior transition has run to GLANCEABLE_HUB - communalSceneInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") runCurrent() clearInvocations(transitionRepository) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt index 409c55144c6a..5ec566bab6d5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos +import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent @@ -49,6 +50,24 @@ class PrimaryBouncerToLockscreenTransitionViewModelTest : SysuiTestCase() { val underTest = kosmos.primaryBouncerToLockscreenTransitionViewModel @Test + fun lockscreenAlphaStartsFromViewStateAccessorAlpha() = + testScope.runTest { + val viewState = ViewStateAccessor(alpha = { 0.5f }) + val alpha by collectLastValue(underTest.lockscreenAlpha(viewState)) + + keyguardTransitionRepository.sendTransitionStep(step(0f, TransitionState.STARTED)) + + keyguardTransitionRepository.sendTransitionStep(step(0f)) + assertThat(alpha).isEqualTo(0.5f) + + keyguardTransitionRepository.sendTransitionStep(step(0.5f)) + assertThat(alpha).isIn(Range.open(0.5f, 1f)) + + keyguardTransitionRepository.sendTransitionStep(step(1f)) + assertThat(alpha).isEqualTo(1f) + } + + @Test fun deviceEntryParentViewAlpha() = testScope.runTest { val deviceEntryParentViewAlpha by collectLastValue(underTest.deviceEntryParentViewAlpha) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt index 46b370fedf37..976dc52b2602 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt @@ -154,7 +154,7 @@ class SysUiViewModelTest : SysuiTestCase() { private class FakeViewModel : SysUiViewModel() { var isActivated = false - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { isActivated = true try { awaitCancellation() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelTest.kt new file mode 100644 index 000000000000..59992650cfc7 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.composefragment.viewmodel + +import android.content.testableContext +import android.testing.TestableLooper.RunWithLooper +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.testing.TestLifecycleOwner +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.qs.fgsManagerController +import com.android.systemui.res.R +import com.android.systemui.shade.largeScreenHeaderHelper +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestResult +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +@RunWithLooper +@OptIn(ExperimentalCoroutinesApi::class) +class QSFragmentComposeViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + + private val lifecycleOwner = + TestLifecycleOwner( + initialState = Lifecycle.State.CREATED, + coroutineDispatcher = kosmos.testDispatcher, + ) + + private val underTest by lazy { + kosmos.qsFragmentComposeViewModelFactory.create(lifecycleOwner.lifecycleScope) + } + + @Before + fun setUp() { + Dispatchers.setMain(kosmos.testDispatcher) + } + + @After + fun teardown() { + Dispatchers.resetMain() + } + + // For now the state changes at 0.5f expansion. This will change once we implement animation + // (and this test will fail) + @Test + fun qsExpansionValueChanges_correctExpansionState() = + with(kosmos) { + testScope.testWithinLifecycle { + val expansionState by collectLastValue(underTest.expansionState) + + underTest.qsExpansionValue = 0f + assertThat(expansionState) + .isEqualTo(QSFragmentComposeViewModel.QSExpansionState.QQS) + + underTest.qsExpansionValue = 0.3f + assertThat(expansionState) + .isEqualTo(QSFragmentComposeViewModel.QSExpansionState.QQS) + + underTest.qsExpansionValue = 0.7f + assertThat(expansionState).isEqualTo(QSFragmentComposeViewModel.QSExpansionState.QS) + + underTest.qsExpansionValue = 1f + assertThat(expansionState).isEqualTo(QSFragmentComposeViewModel.QSExpansionState.QS) + } + } + + @Test + fun qqsHeaderHeight_largeScreenHeader_0() = + with(kosmos) { + testScope.testWithinLifecycle { + val qqsHeaderHeight by collectLastValue(underTest.qqsHeaderHeight) + + testableContext.orCreateTestableResources.addOverride( + R.bool.config_use_large_screen_shade_header, + true + ) + fakeConfigurationRepository.onConfigurationChange() + + assertThat(qqsHeaderHeight).isEqualTo(0) + } + } + + @Test + fun qqsHeaderHeight_noLargeScreenHeader_providedByHelper() = + with(kosmos) { + testScope.testWithinLifecycle { + val qqsHeaderHeight by collectLastValue(underTest.qqsHeaderHeight) + + testableContext.orCreateTestableResources.addOverride( + R.bool.config_use_large_screen_shade_header, + false + ) + fakeConfigurationRepository.onConfigurationChange() + + assertThat(qqsHeaderHeight) + .isEqualTo(largeScreenHeaderHelper.getLargeScreenHeaderHeight()) + } + } + + @Test + fun footerActionsControllerInit() = + with(kosmos) { + testScope.testWithinLifecycle { + underTest + runCurrent() + assertThat(fgsManagerController.initialized).isTrue() + } + } + + private inline fun TestScope.testWithinLifecycle( + crossinline block: suspend TestScope.() -> TestResult + ): TestResult { + return runTest { + lifecycleOwner.setCurrentState(Lifecycle.State.RESUMED) + block().also { lifecycleOwner.setCurrentState(Lifecycle.State.DESTROYED) } + } + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt deleted file mode 100644 index b2f5765d0bc4..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.panels.ui.compose - -import androidx.compose.runtime.mutableStateOf -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.common.shared.model.Icon -import com.android.systemui.common.shared.model.Text -import com.android.systemui.qs.panels.shared.model.SizedTile -import com.android.systemui.qs.panels.shared.model.SizedTileImpl -import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel -import com.android.systemui.qs.pipeline.shared.TileSpec -import com.google.common.truth.Truth.assertThat -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -class DragAndDropStateTest : SysuiTestCase() { - private val listState = EditTileListState(TestEditTiles) - private val underTest = DragAndDropState(mutableStateOf(null), listState) - - @Test - fun isMoving_returnsCorrectValue() { - // Asserts no tiles is moving - TestEditTiles.forEach { assertThat(underTest.isMoving(it.tile.tileSpec)).isFalse() } - - // Start the drag movement - underTest.onStarted(TestEditTiles[0]) - - // Assert that the correct tile is marked as moving - TestEditTiles.forEach { - assertThat(underTest.isMoving(it.tile.tileSpec)) - .isEqualTo(TestEditTiles[0].tile.tileSpec == it.tile.tileSpec) - } - } - - @Test - fun onMoved_updatesList() { - // Start the drag movement - underTest.onStarted(TestEditTiles[0]) - - // Move the tile to the end of the list - underTest.onMoved(listState.tiles[5].tile.tileSpec) - assertThat(underTest.currentPosition()).isEqualTo(5) - - // Move the tile to the middle of the list - underTest.onMoved(listState.tiles[2].tile.tileSpec) - assertThat(underTest.currentPosition()).isEqualTo(2) - } - - @Test - fun onDrop_resetsMovingTile() { - // Start the drag movement - underTest.onStarted(TestEditTiles[0]) - - // Move the tile to the end of the list - underTest.onMoved(listState.tiles[5].tile.tileSpec) - - // Drop the tile - underTest.onDrop() - - // Asserts no tiles is moving - TestEditTiles.forEach { assertThat(underTest.isMoving(it.tile.tileSpec)).isFalse() } - } - - @Test - fun onMoveOutOfBounds_removeMovingTileFromCurrentList() { - // Start the drag movement - underTest.onStarted(TestEditTiles[0]) - - // Move the tile outside of the list - underTest.movedOutOfBounds() - - // Asserts the moving tile is not current - assertThat( - listState.tiles.firstOrNull { it.tile.tileSpec == TestEditTiles[0].tile.tileSpec } - ) - .isNull() - } - - companion object { - private fun createEditTile(tileSpec: String): SizedTile<EditTileViewModel> { - return SizedTileImpl( - EditTileViewModel( - tileSpec = TileSpec.create(tileSpec), - icon = Icon.Resource(0, null), - label = Text.Loaded("unused"), - appName = null, - isCurrent = true, - availableEditActions = emptySet(), - ), - 1, - ) - } - - private val TestEditTiles = - listOf( - createEditTile("tileA"), - createEditTile("tileB"), - createEditTile("tileC"), - createEditTile("tileD"), - createEditTile("tileE"), - createEditTile("tileF"), - ) - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt new file mode 100644 index 000000000000..4d1dd1cce766 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.panels.ui.compose + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.assert +import androidx.compose.ui.test.hasContentDescription +import androidx.compose.ui.test.junit4.ComposeContentTestRule +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onChildAt +import androidx.compose.ui.test.onChildren +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.ContentDescription +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.common.shared.model.Text +import com.android.systemui.qs.panels.shared.model.SizedTile +import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel +import com.android.systemui.qs.pipeline.shared.TileSpec +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class DragAndDropTest : SysuiTestCase() { + @get:Rule val composeRule = createComposeRule() + + // TODO(ostonge): Investigate why drag isn't detected when using performTouchInput + @Composable + private fun EditTileGridUnderTest( + listState: EditTileListState, + onSetTiles: (List<TileSpec>) -> Unit + ) { + DefaultEditTileGrid( + currentListState = listState, + otherTiles = listOf(), + columns = 4, + modifier = Modifier.fillMaxSize(), + onAddTile = { _, _ -> }, + onRemoveTile = {}, + onSetTiles = onSetTiles, + onResize = {}, + ) + } + + @Test + fun draggedTile_shouldDisappear() { + var tiles by mutableStateOf(TestEditTiles) + val listState = EditTileListState(tiles, 4) + composeRule.setContent { + EditTileGridUnderTest(listState) { + tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) } + } + } + composeRule.waitForIdle() + + listState.onStarted(TestEditTiles[0]) + + // Tile is being dragged, it should be replaced with a placeholder + composeRule.onNodeWithContentDescription("tileA").assertDoesNotExist() + + // Available tiles should disappear + composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertDoesNotExist() + + // Remove drop zone should appear + composeRule.onNodeWithText("Remove").assertExists() + + // Every other tile should still be in the same order + composeRule.assertTileGridContainsExactly(listOf("tileB", "tileC", "tileD_large", "tileE")) + } + + @Test + fun draggedTile_shouldChangePosition() { + var tiles by mutableStateOf(TestEditTiles) + val listState = EditTileListState(tiles, 4) + composeRule.setContent { + EditTileGridUnderTest(listState) { + tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) } + } + } + composeRule.waitForIdle() + + listState.onStarted(TestEditTiles[0]) + listState.onMoved(1, false) + listState.onDrop() + + // Available tiles should re-appear + composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists() + + // Remove drop zone should disappear + composeRule.onNodeWithText("Remove").assertDoesNotExist() + + // Tile A and B should swap places + composeRule.assertTileGridContainsExactly( + listOf("tileB", "tileA", "tileC", "tileD_large", "tileE") + ) + } + + @Test + fun draggedTileOut_shouldBeRemoved() { + var tiles by mutableStateOf(TestEditTiles) + val listState = EditTileListState(tiles, 4) + composeRule.setContent { + EditTileGridUnderTest(listState) { + tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) } + } + } + composeRule.waitForIdle() + + listState.onStarted(TestEditTiles[0]) + listState.movedOutOfBounds() + listState.onDrop() + + // Available tiles should re-appear + composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists() + + // Remove drop zone should disappear + composeRule.onNodeWithText("Remove").assertDoesNotExist() + + // Tile A is gone + composeRule.assertTileGridContainsExactly(listOf("tileB", "tileC", "tileD_large", "tileE")) + } + + @Test + fun draggedNewTileIn_shouldBeAdded() { + var tiles by mutableStateOf(TestEditTiles) + val listState = EditTileListState(tiles, 4) + composeRule.setContent { + EditTileGridUnderTest(listState) { + tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) } + } + } + composeRule.waitForIdle() + + listState.onStarted(createEditTile("newTile")) + // Insert after tileD, which is at index 4 + // [ a ] [ b ] [ c ] [ empty ] + // [ tile d ] [ e ] + listState.onMoved(4, insertAfter = true) + listState.onDrop() + + // Available tiles should re-appear + composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists() + + // Remove drop zone should disappear + composeRule.onNodeWithText("Remove").assertDoesNotExist() + + // newTile is added after tileD + composeRule.assertTileGridContainsExactly( + listOf("tileA", "tileB", "tileC", "tileD_large", "newTile", "tileE") + ) + } + + private fun ComposeContentTestRule.assertTileGridContainsExactly(specs: List<String>) { + onNodeWithTag(CURRENT_TILES_GRID_TEST_TAG).onChildren().apply { + fetchSemanticsNodes().forEachIndexed { index, _ -> + get(index).onChildAt(0).assert(hasContentDescription(specs[index])) + } + } + } + + companion object { + private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid" + private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid" + + private fun createEditTile(tileSpec: String): SizedTile<EditTileViewModel> { + return SizedTileImpl( + EditTileViewModel( + tileSpec = TileSpec.create(tileSpec), + icon = + Icon.Resource( + android.R.drawable.star_on, + ContentDescription.Loaded(tileSpec) + ), + label = Text.Loaded(tileSpec), + appName = null, + isCurrent = true, + availableEditActions = emptySet(), + ), + getWidth(tileSpec), + ) + } + + private fun getWidth(tileSpec: String): Int { + return if (tileSpec.endsWith("large")) { + 2 + } else { + 1 + } + } + + private val TestEditTiles = + listOf( + createEditTile("tileA"), + createEditTile("tileB"), + createEditTile("tileC"), + createEditTile("tileD_large"), + createEditTile("tileE"), + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt index a3a6a33f6408..7f01fad1ce55 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt @@ -23,6 +23,9 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.model.GridCell +import com.android.systemui.qs.panels.ui.model.SpacerGridCell +import com.android.systemui.qs.panels.ui.model.TileGridCell import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.pipeline.shared.TileSpec import com.google.common.truth.Truth.assertThat @@ -32,80 +35,130 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class EditTileListStateTest : SysuiTestCase() { - val underTest = EditTileListState(TestEditTiles) + private val underTest = EditTileListState(TestEditTiles, 4) @Test - fun movingNonExistentTile_tileAdded() { - val newTile = createEditTile("other_tile", false) - underTest.move(newTile, TestEditTiles[0].tile.tileSpec) - - assertThat(underTest.tiles[0]).isEqualTo(newTile) - assertThat(underTest.tiles.subList(1, underTest.tiles.size)) - .containsExactly(*TestEditTiles.toTypedArray()) + fun noDrag_listUnchanged() { + underTest.tiles.forEach { assertThat(it).isNotInstanceOf(SpacerGridCell::class.java) } + assertThat(underTest.tiles.map { (it as TileGridCell).tile.tileSpec }) + .containsExactly(*TestEditTiles.map { it.tile.tileSpec }.toTypedArray()) } @Test - fun movingTileToNonExistentTarget_listUnchanged() { - underTest.move(TestEditTiles[0], TileSpec.create("other_tile")) + fun startDrag_listHasSpacers() { + underTest.onStarted(TestEditTiles[0]) + + // [ a ] [ b ] [ c ] [ X ] + // [ Large D ] [ e ] [ X ] + assertThat(underTest.tiles.toStrings()) + .isEqualTo(listOf("a", "b", "c", "spacer", "d", "e", "spacer")) + assertThat(underTest.isMoving(TestEditTiles[0].tile.tileSpec)).isTrue() + assertThat(underTest.dragInProgress).isTrue() + } - assertThat(underTest.tiles).containsExactly(*TestEditTiles.toTypedArray()) + @Test + fun moveDrag_listChanges() { + underTest.onStarted(TestEditTiles[4]) + underTest.onMoved(3, false) + + // Tile E goes to index 3 + // [ a ] [ b ] [ c ] [ e ] + // [ Large D ] [ X ] [ X ] + assertThat(underTest.tiles.toStrings()) + .isEqualTo(listOf("a", "b", "c", "e", "d", "spacer", "spacer")) } @Test - fun movingTileToItself_listUnchanged() { - underTest.move(TestEditTiles[0], TestEditTiles[0].tile.tileSpec) + fun moveDragOnSidesOfLargeTile_listChanges() { + val draggedCell = TestEditTiles[4] + + underTest.onStarted(draggedCell) + underTest.onMoved(4, true) - assertThat(underTest.tiles).containsExactly(*TestEditTiles.toTypedArray()) + // Tile E goes to the right side of tile D, list is unchanged + // [ a ] [ b ] [ c ] [ X ] + // [ Large D ] [ e ] [ X ] + assertThat(underTest.tiles.toStrings()) + .isEqualTo(listOf("a", "b", "c", "spacer", "d", "e", "spacer")) + + underTest.onMoved(4, false) + + // Tile E goes to the left side of tile D, they swap positions + // [ a ] [ b ] [ c ] [ e ] + // [ Large D ] [ X ] [ X ] + assertThat(underTest.tiles.toStrings()) + .isEqualTo(listOf("a", "b", "c", "e", "d", "spacer", "spacer")) } @Test - fun movingTileToSameSection_listUpdates() { - // Move tile at index 0 to index 1. Tile 0 should remain current. - underTest.move(TestEditTiles[0], TestEditTiles[1].tile.tileSpec) + fun moveNewTile_tileIsAdded() { + val newTile = createEditTile("newTile", 2) + + underTest.onStarted(newTile) + underTest.onMoved(5, false) + + // New tile goes to index 5 + // [ a ] [ b ] [ c ] [ X ] + // [ Large D ] [ newTile ] + // [ e ] [ X ] [ X ] [ X ] + assertThat(underTest.tiles.toStrings()) + .isEqualTo( + listOf("a", "b", "c", "spacer", "d", "newTile", "e", "spacer", "spacer", "spacer") + ) + } - // Assert the tiles 0 and 1 have changed places. - assertThat(underTest.tiles[0]).isEqualTo(TestEditTiles[1]) - assertThat(underTest.tiles[1]).isEqualTo(TestEditTiles[0]) + @Test + fun droppedNewTile_spacersDisappear() { + underTest.onStarted(TestEditTiles[0]) + underTest.onDrop() - // Assert the rest of the list is unchanged - assertThat(underTest.tiles.subList(2, 5)) - .containsExactly(*TestEditTiles.subList(2, 5).toTypedArray()) + assertThat(underTest.tiles.toStrings()).isEqualTo(listOf("a", "b", "c", "d", "e")) + assertThat(underTest.isMoving(TestEditTiles[0].tile.tileSpec)).isFalse() + assertThat(underTest.dragInProgress).isFalse() } - fun removingTile_listUpdates() { - // Remove tile at index 0 - underTest.remove(TestEditTiles[0].tile.tileSpec) + @Test + fun movedTileOutOfBounds_tileDisappears() { + underTest.onStarted(TestEditTiles[0]) + underTest.movedOutOfBounds() + + assertThat(underTest.tiles.toStrings()).doesNotContain(TestEditTiles[0].tile.tileSpec.spec) + } - // Assert the tile was removed - assertThat(underTest.tiles).containsExactly(*TestEditTiles.subList(1, 6).toTypedArray()) + private fun List<GridCell>.toStrings(): List<String> { + return map { + if (it is TileGridCell) { + it.tile.tileSpec.spec + } else { + "spacer" + } + } } companion object { - private fun createEditTile( - tileSpec: String, - isCurrent: Boolean - ): SizedTile<EditTileViewModel> { + private fun createEditTile(tileSpec: String, width: Int): SizedTile<EditTileViewModel> { return SizedTileImpl( EditTileViewModel( tileSpec = TileSpec.create(tileSpec), icon = Icon.Resource(0, null), label = Text.Loaded("unused"), appName = null, - isCurrent = isCurrent, + isCurrent = true, availableEditActions = emptySet(), ), - 1, + width, ) } + // [ a ] [ b ] [ c ] + // [ Large D ] [ e ] [ f ] private val TestEditTiles = listOf( - createEditTile("tileA", true), - createEditTile("tileB", true), - createEditTile("tileC", true), - createEditTile("tileD", false), - createEditTile("tileE", false), - createEditTile("tileF", false), + createEditTile("a", 1), + createEditTile("b", 1), + createEditTile("c", 1), + createEditTile("d", 2), + createEditTile("e", 1), ) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt index 314631823e96..8995f46e7a72 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt @@ -24,7 +24,6 @@ import android.os.UserHandle import android.service.quicksettings.Tile import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE import com.android.systemui.Flags.FLAG_QS_NEW_TILES import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -107,7 +106,6 @@ class CurrentTilesInteractorImplTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) - mSetFlagsRule.enableFlags(FLAG_QS_NEW_PIPELINE) mSetFlagsRule.enableFlags(FLAG_QS_NEW_TILES) userRepository.setUserInfos(listOf(USER_INFO_0, USER_INFO_1)) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/NoLowNumberOfTilesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/NoLowNumberOfTilesTest.kt index e8ad038f8fbc..00c720475fb1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/NoLowNumberOfTilesTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/NoLowNumberOfTilesTest.kt @@ -20,7 +20,6 @@ import android.content.ComponentName import android.content.pm.UserInfo import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest -import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.Kosmos @@ -98,8 +97,6 @@ class NoLowNumberOfTilesTest : SysuiTestCase() { @Before fun setUp() { - mSetFlagsRule.enableFlags(Flags.FLAG_QS_NEW_PIPELINE) - with(kosmos) { restoreReconciliationInteractor.start() autoAddInteractor.init(kosmos.currentTilesInteractor) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt index dffd0d72969c..6bcaea47cab1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt @@ -20,7 +20,6 @@ import android.content.pm.UserInfo import android.os.UserManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest -import com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.Kosmos @@ -59,6 +58,7 @@ class WorkProfileAutoAddedAfterRestoreTest : SysuiTestCase() { // Getter here so it can change when there is a managed profile. private val workTileAvailable: Boolean get() = hasManagedProfile() + private val currentUser: Int get() = kosmos.userTracker.userId @@ -67,8 +67,6 @@ class WorkProfileAutoAddedAfterRestoreTest : SysuiTestCase() { @Before fun setUp() { - mSetFlagsRule.enableFlags(FLAG_QS_NEW_PIPELINE) - kosmos.qsTileFactory = FakeQSFactory(::tileCreator) kosmos.restoreReconciliationInteractor.start() kosmos.autoAddInteractor.init(kosmos.currentTilesInteractor) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt index 036380853a71..f26a9db56450 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt @@ -36,11 +36,7 @@ import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintA import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope -import com.android.systemui.media.controls.data.repository.mediaFilterRepository -import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor -import com.android.systemui.media.controls.shared.model.MediaData -import com.android.systemui.qs.FooterActionsController -import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel +import com.android.systemui.lifecycle.activateIn import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneBackInteractor @@ -49,41 +45,29 @@ import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.scene.shared.model.SceneFamilies import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModelFactory -import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory import com.android.systemui.testKosmos -import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito.times -import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) @RunWithLooper @EnableSceneContainer -class QuickSettingsSceneViewModelTest : SysuiTestCase() { +class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() }) - private val footerActionsViewModel = mock<FooterActionsViewModel>() - private val footerActionsViewModelFactory = - mock<FooterActionsViewModel.Factory> { - whenever(create(any())).thenReturn(footerActionsViewModel) - } - private val footerActionsController = mock<FooterActionsController>() private val sceneInteractor = kosmos.sceneInteractor private val sceneBackInteractor = kosmos.sceneBackInteractor private val sceneContainerStartable = kosmos.sceneContainerStartable - private lateinit var underTest: QuickSettingsSceneViewModel + private lateinit var underTest: QuickSettingsSceneActionsViewModel @Before fun setUp() { @@ -91,22 +75,18 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { sceneContainerStartable.start() underTest = - QuickSettingsSceneViewModel( - brightnessMirrorViewModelFactory = kosmos.brightnessMirrorViewModelFactory, - shadeHeaderViewModelFactory = kosmos.shadeHeaderViewModelFactory, + QuickSettingsSceneActionsViewModel( qsSceneAdapter = qsFlexiglassAdapter, - footerActionsViewModelFactory = footerActionsViewModelFactory, - footerActionsController = footerActionsController, sceneBackInteractor = sceneBackInteractor, - mediaCarouselInteractor = kosmos.mediaCarouselInteractor, ) + underTest.activateIn(testScope) } @Test fun destinations_whenNotCustomizing_unlocked() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeAuthenticationRepository.setAuthenticationMethod( @@ -116,7 +96,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { SuccessFingerprintAuthenticationStatus(0, true) ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -135,7 +115,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) qsFlexiglassAdapter.setCustomizing(false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val currentScene by collectLastValue(sceneInteractor.currentScene) val backScene by collectLastValue(sceneBackInteractor.backScene) @@ -145,7 +125,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.QuickSettings) assertThat(backScene).isEqualTo(Scenes.Lockscreen) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Lockscreen), @@ -164,7 +144,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) qsFlexiglassAdapter.setCustomizing(false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val currentScene by collectLastValue(sceneInteractor.currentScene) val backScene by collectLastValue(sceneBackInteractor.backScene) @@ -176,7 +156,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Gone) assertThat(backScene).isNull() - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -194,7 +174,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenNotCustomizing_authMethodSwipe_lockscreenNotDismissed() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true) @@ -202,7 +182,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { AuthenticationMethodModel.None ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -220,17 +200,17 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenCustomizing_noDestinations() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) qsFlexiglassAdapter.setCustomizing(true) - assertThat(destinations).isEmpty() + assertThat(actions).isEmpty() } @Test fun destinations_whenNotCustomizing_inSplitShade_unlocked() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, true) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeAuthenticationRepository.setAuthenticationMethod( @@ -240,7 +220,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { SuccessFingerprintAuthenticationStatus(0, true) ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -258,49 +238,9 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenCustomizing_inSplitShade_noDestinations() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, true) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) qsFlexiglassAdapter.setCustomizing(true) - assertThat(destinations).isEmpty() - } - - @Test - fun gettingViewModelInitializesControllerOnlyOnce() { - underTest.getFooterActionsViewModel(mock()) - underTest.getFooterActionsViewModel(mock()) - - verify(footerActionsController, times(1)).init() - } - - @Test - fun addAndRemoveMedia_mediaVisibilityIsUpdated() = - testScope.runTest { - kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) - val isMediaVisible by collectLastValue(underTest.isMediaVisible) - val userMedia = MediaData(active = true) - - assertThat(isMediaVisible).isFalse() - - kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) - - assertThat(isMediaVisible).isTrue() - - kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) - - assertThat(isMediaVisible).isFalse() - } - - @Test - fun addInactiveMedia_mediaVisibilityIsUpdated() = - testScope.runTest { - kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) - val isMediaVisible by collectLastValue(underTest.isMediaVisible) - val userMedia = MediaData(active = false) - - assertThat(isMediaVisible).isFalse() - - kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) - - assertThat(isMediaVisible).isTrue() + assertThat(actions).isEmpty() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt new file mode 100644 index 000000000000..1118a6150fcc --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.ui.viewmodel + +import android.testing.TestableLooper.RunWithLooper +import androidx.lifecycle.LifecycleOwner +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.flags.Flags +import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn +import com.android.systemui.media.controls.data.repository.mediaFilterRepository +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel +import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter +import com.android.systemui.scene.domain.startable.sceneContainerStartable +import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModelFactory +import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@SmallTest +@RunWith(AndroidJUnit4::class) +@RunWithLooper +@EnableSceneContainer +class QuickSettingsSceneContentViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() }) + private val footerActionsViewModel = mock<FooterActionsViewModel>() + private val footerActionsViewModelFactory = + mock<FooterActionsViewModel.Factory> { + whenever(create(any<LifecycleOwner>())).thenReturn(footerActionsViewModel) + } + private val footerActionsController = mock<FooterActionsController>() + + private val sceneContainerStartable = kosmos.sceneContainerStartable + + private lateinit var underTest: QuickSettingsSceneContentViewModel + + @Before + fun setUp() { + kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false) + + sceneContainerStartable.start() + underTest = + QuickSettingsSceneContentViewModel( + brightnessMirrorViewModelFactory = kosmos.brightnessMirrorViewModelFactory, + shadeHeaderViewModelFactory = kosmos.shadeHeaderViewModelFactory, + qsSceneAdapter = qsFlexiglassAdapter, + footerActionsViewModelFactory = footerActionsViewModelFactory, + footerActionsController = footerActionsController, + mediaCarouselInteractor = kosmos.mediaCarouselInteractor, + ) + underTest.activateIn(testScope) + } + + @Test + fun gettingViewModelInitializesControllerOnlyOnce() { + underTest.getFooterActionsViewModel(mock()) + underTest.getFooterActionsViewModel(mock()) + + verify(footerActionsController, times(1)).init() + } + + @Test + fun addAndRemoveMedia_mediaVisibilityIsUpdated() = + testScope.runTest { + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = true) + + assertThat(isMediaVisible).isFalse() + + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + + kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) + + assertThat(isMediaVisible).isFalse() + } + + @Test + fun addInactiveMedia_mediaVisibilityIsUpdated() = + testScope.runTest { + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = false) + + assertThat(isMediaVisible).isFalse() + + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 66e45ab8ccbe..9122528e5c11 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -36,10 +36,10 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel -import com.android.systemui.bouncer.ui.viewmodel.bouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModel import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.coroutines.collectLastValue @@ -133,13 +133,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { sceneInteractor = sceneInteractor, falsingInteractor = kosmos.falsingInteractor, powerInteractor = kosmos.powerInteractor, + motionEventHandlerReceiver = {}, ) .apply { setTransitionState(transitionState) } } private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor - private lateinit var bouncerViewModel: BouncerViewModel + private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel private val lockscreenSceneActionsViewModel by lazy { LockscreenSceneActionsViewModel( @@ -187,7 +188,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { } bouncerActionButtonInteractor = kosmos.bouncerActionButtonInteractor - bouncerViewModel = kosmos.bouncerViewModel + bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel shadeSceneContentViewModel = kosmos.shadeSceneContentViewModel shadeSceneActionsViewModel = kosmos.shadeSceneActionsViewModel @@ -198,6 +199,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { lockscreenSceneActionsViewModel.activateIn(testScope) shadeSceneContentViewModel.activateIn(testScope) shadeSceneActionsViewModel.activateIn(testScope) + bouncerSceneContentViewModel.activateIn(testScope) + sceneContainerViewModel.activateIn(testScope) assertWithMessage("Initial scene key mismatch!") .that(sceneContainerViewModel.currentScene.value) @@ -325,6 +328,16 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { } @Test + fun lockDeviceLocksDevice() = + testScope.runTest { + unlockDevice() + assertCurrentScene(Scenes.Gone) + + lockDevice() + assertCurrentScene(Scenes.Lockscreen) + } + + @Test fun deviceGoesToSleep_switchesToLockscreen() = testScope.runTest { unlockDevice() @@ -397,7 +410,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer) emulateUserDrivenTransition(to = upDestinationSceneKey) - val bouncerActionButton by collectLastValue(bouncerViewModel.actionButton) + val bouncerActionButton by collectLastValue(bouncerSceneContentViewModel.actionButton) assertWithMessage("Bouncer action button not visible") .that(bouncerActionButton) .isNotNull() @@ -417,7 +430,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer) emulateUserDrivenTransition(to = upDestinationSceneKey) - val bouncerActionButton by collectLastValue(bouncerViewModel.actionButton) + val bouncerActionButton by collectLastValue(bouncerSceneContentViewModel.actionButton) assertWithMessage("Bouncer action button not visible during call") .that(bouncerActionButton) .isNotNull() @@ -568,7 +581,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { bouncerSceneJob = if (to == Scenes.Bouncer) { testScope.backgroundScope.launch { - bouncerViewModel.authMethodViewModel.collect { + bouncerSceneContentViewModel.authMethodViewModel.collect { // Do nothing. Need this to turn this otherwise cold flow, hot. } } @@ -613,7 +626,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!") .that(authMethod.isSecure) .isTrue() - + kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "") runCurrent() } @@ -644,7 +657,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertWithMessage("Cannot enter PIN when not on the Bouncer scene!") .that(getCurrentSceneInUi()) .isEqualTo(Scenes.Bouncer) - val authMethodViewModel by collectLastValue(bouncerViewModel.authMethodViewModel) + val authMethodViewModel by + collectLastValue(bouncerSceneContentViewModel.authMethodViewModel) assertWithMessage("Cannot enter PIN when not using a PIN authentication method!") .that(authMethodViewModel) .isInstanceOf(PinBouncerViewModel::class.java) @@ -672,7 +686,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertWithMessage("Cannot enter PIN when not on the Bouncer scene!") .that(getCurrentSceneInUi()) .isEqualTo(Scenes.Bouncer) - val authMethodViewModel by collectLastValue(bouncerViewModel.authMethodViewModel) + val authMethodViewModel by + collectLastValue(bouncerSceneContentViewModel.authMethodViewModel) assertWithMessage("Cannot enter PIN when not using a PIN authentication method!") .that(authMethodViewModel) .isInstanceOf(PinBouncerViewModel::class.java) @@ -719,7 +734,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { /** Emulates the dismissal of the IME (soft keyboard). */ private fun TestScope.dismissIme() { - (bouncerViewModel.authMethodViewModel.value as? PasswordBouncerViewModel)?.let { + (bouncerSceneContentViewModel.authMethodViewModel.value as? PasswordBouncerViewModel)?.let { it.onImeDismissed() runCurrent() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index ea95aab4a1c4..f85823ad7c33 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.scene.ui.viewmodel import android.view.MotionEvent @@ -25,6 +27,7 @@ import com.android.systemui.classifier.fakeFalsingManager import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor @@ -37,6 +40,8 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -57,6 +62,9 @@ class SceneContainerViewModelTest : SysuiTestCase() { private lateinit var underTest: SceneContainerViewModel + private lateinit var activationJob: Job + private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null + @Before fun setUp() { underTest = @@ -64,10 +72,28 @@ class SceneContainerViewModelTest : SysuiTestCase() { sceneInteractor = sceneInteractor, falsingInteractor = kosmos.falsingInteractor, powerInteractor = kosmos.powerInteractor, + motionEventHandlerReceiver = { motionEventHandler -> + this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler + }, ) + activationJob = Job() + underTest.activateIn(testScope, activationJob) } @Test + fun activate_setsMotionEventHandler() = + testScope.runTest { assertThat(motionEventHandler).isNotNull() } + + @Test + fun deactivate_clearsMotionEventHandler() = + testScope.runTest { + activationJob.cancel() + runCurrent() + + assertThat(motionEventHandler).isNull() + } + + @Test fun isVisible() = testScope.runTest { val isVisible by collectLastValue(underTest.isVisible) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java index 9005ae3c3d41..89aa670e5f0c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java @@ -241,7 +241,7 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { alm.showNotification(entry); final boolean removedImmediately = alm.removeNotification( - entry.getKey(), /* releaseImmediately = */ false); + entry.getKey(), /* releaseImmediately = */ false, "removeDeferred"); assertFalse(removedImmediately); assertTrue(alm.isHeadsUpEntry(entry.getKey())); } @@ -254,7 +254,7 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { alm.showNotification(entry); final boolean removedImmediately = alm.removeNotification( - entry.getKey(), /* releaseImmediately = */ true); + entry.getKey(), /* releaseImmediately = */ true, "forceRemove"); assertTrue(removedImmediately); assertFalse(alm.isHeadsUpEntry(entry.getKey())); } @@ -430,7 +430,7 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { hum.showNotification(entry); final boolean removedImmediately = hum.removeNotification( - entry.getKey(), /* releaseImmediately = */ false); + entry.getKey(), /* releaseImmediately = */ false, "beforeMinimumDisplayTime"); assertFalse(removedImmediately); assertTrue(hum.isHeadsUpEntry(entry.getKey())); @@ -452,7 +452,7 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { assertTrue(hum.isHeadsUpEntry(entry.getKey())); final boolean removedImmediately = hum.removeNotification( - entry.getKey(), /* releaseImmediately = */ false); + entry.getKey(), /* releaseImmediately = */ false, "afterMinimumDisplayTime"); assertTrue(removedImmediately); assertFalse(hum.isHeadsUpEntry(entry.getKey())); } @@ -466,7 +466,7 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { hum.showNotification(entry); final boolean removedImmediately = hum.removeNotification( - entry.getKey(), /* releaseImmediately = */ true); + entry.getKey(), /* releaseImmediately = */ true, "afterMinimumDisplayTime"); assertTrue(removedImmediately); assertFalse(hum.isHeadsUpEntry(entry.getKey())); } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt index 7a6838a6c9ac..ca106fa01f9a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt @@ -179,8 +179,8 @@ class HeadsUpManagerPhoneTest(flags: FlagsParameterization) : BaseHeadsUpManager mContext .getOrCreateTestableResources() .addOverride(R.integer.ambient_notification_extension_time, 500) - mAvalancheController = AvalancheController(dumpManager, mUiEventLogger, - mHeadsUpManagerLogger, mBgHandler) + mAvalancheController = + AvalancheController(dumpManager, mUiEventLogger, mHeadsUpManagerLogger, mBgHandler) } @Test @@ -200,7 +200,12 @@ class HeadsUpManagerPhoneTest(flags: FlagsParameterization) : BaseHeadsUpManager hmp.addSwipedOutNotification(entry.key) // Remove should succeed because the notification is swiped out - val removedImmediately = hmp.removeNotification(entry.key, /* releaseImmediately= */ false) + val removedImmediately = + hmp.removeNotification( + entry.key, + /* releaseImmediately= */ false, + /* reason= */ "swipe out" + ) Assert.assertTrue(removedImmediately) Assert.assertFalse(hmp.isHeadsUpEntry(entry.key)) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java index 69207ba07e6e..3efabd743141 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java @@ -100,7 +100,7 @@ class TestableHeadsUpManager extends BaseHeadsUpManager { @Override public boolean removeNotification(@NonNull String key, boolean releaseImmediately, - boolean animate) { + boolean animate, @NonNull String reason) { throw new UnsupportedOperationException(); } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt index bcad7e7bc31c..54b7d25325c5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt @@ -23,6 +23,7 @@ import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.notification.modes.TestModeBuilder +import com.android.settingslib.notification.modes.ZenMode import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testDispatcher @@ -30,6 +31,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogDelegate +import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogEventLogger import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -40,6 +42,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.clearInvocations import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.times import org.mockito.kotlin.verify @SmallTest @@ -50,9 +53,16 @@ class ModesDialogViewModelTest : SysuiTestCase() { private val repository = kosmos.fakeZenModeRepository private val interactor = kosmos.zenModeInteractor private val mockDialogDelegate = kosmos.mockModesDialogDelegate + private val mockDialogEventLogger = kosmos.mockModesDialogEventLogger private val underTest = - ModesDialogViewModel(context, interactor, kosmos.testDispatcher, mockDialogDelegate) + ModesDialogViewModel( + context, + interactor, + kosmos.testDispatcher, + mockDialogDelegate, + mockDialogEventLogger + ) @Test fun tiles_filtersOutUserDisabledModes() = @@ -432,4 +442,84 @@ class ModesDialogViewModelTest : SysuiTestCase() { assertThat(intent.extras?.getString(Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID)) .isEqualTo("B") } + + @Test + fun onClick_logsOnOffEvents() = + testScope.runTest { + val tiles by collectLastValue(underTest.tiles) + + repository.addModes( + listOf( + TestModeBuilder.MANUAL_DND_ACTIVE, + TestModeBuilder() + .setId("id1") + .setName("Inactive Mode One") + .setActive(false) + .setManualInvocationAllowed(true) + .build(), + TestModeBuilder() + .setId("id2") + .setName("Active Non-Invokable Mode Two") // but can be turned off by tile + .setActive(true) + .setManualInvocationAllowed(false) + .build(), + ) + ) + runCurrent() + + assertThat(tiles?.size).isEqualTo(3) + + // Trigger onClick for each tile in sequence + tiles?.forEach { it.onClick.invoke() } + runCurrent() + + val onModeCaptor = argumentCaptor<ZenMode>() + val offModeCaptor = argumentCaptor<ZenMode>() + + // manual mode and mode 2 should have turned off + verify(mockDialogEventLogger, times(2)).logModeOff(offModeCaptor.capture()) + val off0 = offModeCaptor.firstValue + assertThat(off0.isManualDnd).isTrue() + + val off1 = offModeCaptor.secondValue + assertThat(off1.id).isEqualTo("id2") + + // should also have logged turning mode 1 on + verify(mockDialogEventLogger).logModeOn(onModeCaptor.capture()) + val on = onModeCaptor.lastValue + assertThat(on.id).isEqualTo("id1") + } + + @Test + fun onLongClick_logsSettingsEvents() = + testScope.runTest { + val tiles by collectLastValue(underTest.tiles) + + repository.addModes( + listOf( + TestModeBuilder.MANUAL_DND_ACTIVE, + TestModeBuilder() + .setId("id1") + .setName("Inactive Mode One") + .setActive(false) + .setManualInvocationAllowed(true) + .build(), + ) + ) + runCurrent() + + assertThat(tiles?.size).isEqualTo(2) + val modeCaptor = argumentCaptor<ZenMode>() + + // long click manual DND and then automatic mode + tiles?.forEach { it.onLongClick.invoke() } + runCurrent() + + verify(mockDialogEventLogger, times(2)).logModeSettings(modeCaptor.capture()) + val manualMode = modeCaptor.firstValue + assertThat(manualMode.isManualDnd).isTrue() + + val automaticMode = modeCaptor.lastValue + assertThat(automaticMode.id).isEqualTo("id1") + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt index 7385a4731401..7c55f7a91a76 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt @@ -32,7 +32,6 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.volume.data.repository.TestAudioDevicesFactory import com.android.systemui.volume.data.repository.audioRepository -import com.android.systemui.volume.data.repository.audioSharingRepository import com.android.systemui.volume.domain.model.AudioOutputDevice import com.android.systemui.volume.localMediaController import com.android.systemui.volume.localMediaRepository @@ -222,32 +221,4 @@ class AudioOutputInteractorTest : SysuiTestCase() { val testIcon = TestStubDrawable() } - - @Test - fun inAudioSharing_returnTrue() { - with(kosmos) { - testScope.runTest { - audioSharingRepository.setInAudioSharing(true) - - val inAudioSharing by collectLastValue(underTest.isInAudioSharing) - runCurrent() - - assertThat(inAudioSharing).isTrue() - } - } - } - - @Test - fun notInAudioSharing_returnFalse() { - with(kosmos) { - testScope.runTest { - audioSharingRepository.setInAudioSharing(false) - - val inAudioSharing by collectLastValue(underTest.isInAudioSharing) - runCurrent() - - assertThat(inAudioSharing).isFalse() - } - } - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt index a1fcfcd0f749..c9d147b6c81c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractorTest.kt @@ -49,6 +49,24 @@ class AudioSharingInteractorTest : SysuiTestCase() { } @Test + fun handleInAudioSharingChange() { + with(kosmos) { + testScope.runTest { + with(audioSharingRepository) { setInAudioSharing(true) } + val inAudioSharing by collectLastValue(underTest.isInAudioSharing) + runCurrent() + + Truth.assertThat(inAudioSharing).isEqualTo(true) + + with(audioSharingRepository) { setInAudioSharing(false) } + runCurrent() + + Truth.assertThat(inAudioSharing).isEqualTo(false) + } + } + } + + @Test fun handlePrimaryGroupChange_nullVolume() { with(kosmos) { testScope.runTest { diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index 57fd9ea8319f..d069c0181218 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -71,7 +71,7 @@ <string name="kg_prompt_after_dpm_lock" msgid="6002804765868345917">"لمزيد من الأمان، تم قفل الجهاز وفقًا لسياسة العمل."</string> <string name="kg_prompt_after_user_lockdown_pin" msgid="5374732179740050373">"يجب إدخال رقم التعريف الشخصي بعد إلغاء الفتح الذكي."</string> <string name="kg_prompt_after_user_lockdown_password" msgid="9097968458291129795">"يجب إدخال كلمة المرور بعد إلغاء الفتح الذكي."</string> - <string name="kg_prompt_after_user_lockdown_pattern" msgid="215072203613597906">"يجب رسم النقش بعد إلغاء التأمين."</string> + <string name="kg_prompt_after_user_lockdown_pattern" msgid="215072203613597906">"يجب رسم النقش بعد إلغاء الفتح الذكي."</string> <string name="kg_prompt_unattended_update" msgid="4366635751738712452">"سيتم تثبيت التحديث عندما لا يكون الجهاز قيد الاستخدام."</string> <string name="kg_prompt_pin_auth_timeout" msgid="5868644725126275245">"يجب تعزيز الأمان. لم يُستخدَم رقم PIN لبعض الوقت."</string> <string name="kg_prompt_password_auth_timeout" msgid="5809110458491920871">"يجب تعزيز الأمان. لم تستخدَم كلمة المرور لبعض الوقت."</string> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index fd90d08caf9e..cf2057cafb8b 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -57,7 +57,7 @@ <string name="kg_wrong_pin" msgid="4160978845968732624">"Неверный PIN-код"</string> <string name="kg_wrong_pin_try_again" msgid="3129729383303430190">"Неверный PIN-код."</string> <string name="kg_wrong_input_try_fp_suggestion" msgid="3143861542242024833">"Повторите попытку или используйте отпечаток пальца."</string> - <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отпечаток не распознан."</string> + <string name="kg_fp_not_recognized" msgid="5183108260932029241">"Отпечаток не распознан"</string> <string name="bouncer_face_not_recognized" msgid="1666128054475597485">"Лицо не распознано."</string> <string name="kg_bio_try_again_or_pin" msgid="4752168242723808390">"Повторите попытку или введите PIN-код."</string> <string name="kg_bio_try_again_or_password" msgid="1473132729225398039">"Повторите попытку или введите пароль."</string> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 8c685ffda2f7..9c4c060ef1e2 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Skermopnemer"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Begin opneem?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Terwyl jy opneem, het Android toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Terwyl jy ’n app opneem, het Android toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Begin opneem"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Neem oudio op"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Toesteloudio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Klank vanaf jou toestel, soos musiek, oproepe en luitone"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Stuur"</string> <string name="cancel" msgid="1089011503403416730">"Kanselleer"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Applogo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bevestig"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Probeer weer"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tik om stawing te kanselleer"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nuwe toestel saam te bind"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kon nie voorafstelling opdateer nie"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voorafstelling"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Intydse Onderskrifte"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Intydse Onderskrifte"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokkeer toestelmikrofoon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokkeer toestelkamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokkeer toestelkamera en mikrofoon?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Af"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Stel op"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Bestuur in instellings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Geen aktiewe modusse nie}=1{{mode} is aktief}other{# modusse is aktief}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers, herinneringe, geleenthede en bellers wat jy spesifiseer. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jy sal nie deur geluide en vibrasies gepla word nie, behalwe deur wekkers. Jy sal steeds enigiets hoor wat jy kies om te speel, insluitend musiek, video\'s en speletjies."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Pasmaak"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans stadig • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Legstukke op sluitskerm"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk is by sluitskerm gevoeg"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pasmaak"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Maak toe"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sal toegang hê tot al die inligting wat op jou skerm sigbaar is of op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto’s, boodskappe en oudio wat jy speel."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Begin opneem of uitsaai?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Die diens wat hierdie funksie verskaf, sal toegang hê tot al die inligting wat op jou skerm sigbaar is of op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto’s, boodskappe en oudio wat jy speel."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Hele skerm"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"’n Enkele app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Deel of neem ’n app op"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Begin opneem of uitsaai met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Wanneer jy deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Wanneer jy ’n app deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Begin"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deel jou skerm met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deel een app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deel hele skerm"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wanneer jy jou hele skerm deel, is enigiets op jou skerm sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wanneer jy ’n app deel, is enigiets wat in die app wys of speel, sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deel skerm"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> het hierdie opsie gedeaktiveer"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Begin uitsaai?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Wanneer jy uitsaai, het Android toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Wanneer jy ’n app uitsaai, het Android toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Begin uitsaai"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Saai jou skerm uit?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Saai een app uit"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Saai hele skerm uit"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Wanneer jy jou hele skerm uitsaai, is enigiets op jou skerm sigbaar. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Wanneer jy ’n app uitsaai, is enigiets wat in die app wys of speel, sigbaar. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Saai skerm uit"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Begin deel?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Wanneer jy deel, opneem of uitsaai, het Android toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Wanneer jy ’n app deel, opneem of uitsaai, het Android toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Begin"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Volgende"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Deling word onderbreek wanneer jy apps wissel"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Deel eerder hierdie app"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Skakel terug"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Toeganklikheid"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Kortpadsleutels"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Soekkortpaaie"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Geen soekresultate nie"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Vou ikoon in"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vou ikoon uit"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Tuisgebaar"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handelingsleutel"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Uitstekende werk!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gaan terug"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Swiep enige plek op die raakpaneel links of regs met drie vingers om terug te gaan.\n\nJy kan ook die kortpadsleutelhandeling + Esc hiervoor gebruik."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gaan na tuisskerm"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Swiep enige tyd van die onderkant van jou skerm af op met drie vingers om na jou tuisskerm toe te gaan."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Raakpaneel wat drie vingers wat regs en links beweeg wys"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Toestelskerm wat animasie vir teruggebaar wys"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Sleutelbordlig"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Vlak %1$d van %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Huiskontroles"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Swiep op met drie vingers op die raakpaneel om terug na die tuisskerm te gaan"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Swiep op en hou met drie vingers op die raakpaneel om onlangse apps te bekyk"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Druk die handelingsleutel op jou sleutelbord om al jou apps te bekyk"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Gewysig"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ontsluit om te kyk"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Gebruik jou raakpaneel om terug te gaan"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swiep links of regs met drie vingers. Tik om meer gebare te leer."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Gebruik jou raakpaneel om na die tuisskerm toe te gaan"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swiep op en hou met drie vingers. Tik om meer gebare te leer."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gebruik jou sleutelbord om alle apps te bekyk"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk enige tyd die handelingsleutel. Tik om meer gebare te leer."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra donker is nou deel van die helderheidbalk"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Jy kan nou die skerm ekstra donker maak deur die helderheidvlak vanaf die bokant van jou skerm nog laer te maak.\n\nDit werk die beste wanneer jy in ’n donker omgewing is."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Verwyder kortpad vir ekstra donker"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kortpad vir ekstra donker is verwyder. Gebruik die gewone helderheidbalk om jou helderheid te verlaag."</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 26e5c1e5d544..e35162a89da4 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"የማያ መቅረጫ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገፅ ቀረጻን በማሰናዳት ላይ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገፅ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"መቅረጽ ይጀመር?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"እርስዎ ሲቀርጹ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"እርስዎ አንድን መተግበሪያ ሲቀርጹ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"መቅረጽ ጀምር"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ኦዲዮን ቅረጽ"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"የመሣሪያ ኦዲዮ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"እንደ ሙዚቃ፣ ጥሪዎች እና የጥሪ ቅላጼዎች ያሉ የመሣሪያዎ ድምፅ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ላክ"</string> <string name="cancel" msgid="1089011503403416730">"ይቅር"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"የመተግበሪያ ዓርማ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"አረጋግጥ"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"እንደገና ይሞክሩ"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ማረጋገጥን ለመሰረዝ መታ ያድርጉ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"አዲስ መሣሪያ ለማጣመር ጠቅ ያድርጉ"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ቅድመ-ቅምጥን ማዘመን አልተቻለም"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ቅድመ-ቅምጥ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"የቀጥታ ስርጭት መግለጫ ጽሁፍ"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"የቀጥታ ስርጭት መግለጫ ጽሁፍ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"የመሣሪያ ማይክሮፎን እገዳ ይነሳ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"የመሣሪያ ካሜራ እገዳ ይነሳ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"የመሣሪያ ካሜራ እና ማይክሮፎን እገዳ ይነሳ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ቅንብሮች"</string> <string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ጠፍቷል"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"አዋቅር"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"በቅንብሮች ውስጥ አስተዳድር"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ምንም ገቢር ሁነታዎች የሉም}=1{{mode} ገቢር ነው}one{# ሁኔታ ገቢር ነው}other{# ሁኔታዎች ገቢር ናቸው}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"እርስዎ ከወሰንዋቸው ማንቂያዎች፣ አስታዋሾች፣ ክስተቶች እና ደዋዮች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ከማንቂያዎች በስተቀር፣ በድምጾች እና ንዝረቶች አይረበሹም። ሙዚቃ፣ ቪዲዮዎች እና ጨዋታዎች ጨምሮ ለመጫወት የሚመርጡትን ማንኛውም ነገር አሁንም ይሰማሉ።"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"አብጅ"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ምግብሮች በማያ ገጽ ቁልፍ ላይ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር ወደ ማያ ገፅ ቁልፍ ታክሏል"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"አብጅ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"አሰናብት"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በእርስዎ ማያ ገጽ ላይ ለሚታየው ወይም በሚቀረጽበት ወይም cast በሚደረግበት ጊዜ በእርስዎ መሣሪያ ላይ ለሚጫወተው ሁሉም መረጃ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚያጫውቱትን ኦዲዮ የመሳሰለ መረጃን ያካትታል።"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"መቅረጽ ወይም cast ማድረግ ይጀመር?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ይህን ተግባር የሚያቀርበው አገልግሎት በእርስዎ ማያ ገጽ ላይ ለሚታየው ወይም በሚቀረጽበት ወይም cast በሚደረግበት ጊዜ በእርስዎ መሣሪያ ላይ ለሚጫወተው ሁሉም መረጃ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚያጫውቱትን ኦዲዮ የመሳሰለ መረጃን ያካትታል።"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"መላው ማያ ገጽ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"አንድ ነጠላ መተግበሪያ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"መተግበሪያን ያጋሩ ወይም ይቅረጹ"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"በ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> መቅረጽ ወይም cast ማድረግ ይጀመር?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"እርስዎ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"አንድን መተግበሪያ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ጀምር"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ማያ ገፅዎን ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ያጋራሉ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"አንድ መተግበሪያ ያጋሩ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"መላውን ማያ ገፅ ያጋሩ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"እርስዎ ሙሉ ማያ ገፅዎን ሲያጋሩ በማያ ገፅዎ ላይ ያለው ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"መተግበሪያን ሲያጋሩ በዚያ መተግበሪያ ውስጥ የሚታይ ወይም የሚጫወት ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ማያ ገፅ አጋራ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ይህን አማራጭ አሰናክሏል"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"cast ማድረግ ይጀምር?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"እርስዎ cast በሚያደርጉበት ጊዜ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"አንድን መተግበሪያ cast ሲያደርጉ Android በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ ይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"cast ማድረግ ይጀምር"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ማያ ገፅዎ cast ይደረግ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"አንድ መተግበሪያ cast ያድርጉ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"መላውን ማያ ገፅ cast ያድርጉ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"እርስዎ ሙሉ ማያ ገፅዎን cast ሲያደርጉ በማያ ገፅዎ ላይ ያለው ማንኛውም ነገር ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"መተግበሪያን cast ሲያደርጉ በዚያ መተግበሪያ ውስጥ የሚታይ ወይም የሚጫወት ማንኛውም ነገር ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"ማያ ገፅ Cast አድርግ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ማጋራት ይጀምር?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"እርስዎ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"እርስዎ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ጀምር"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ቀጣይ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"መተግበሪያዎችን በሚቀያይሩበት ጊዜ ለአፍታ ማቆሞችን ማጋራት"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"በምትኩ ይህን መተግበሪያ ያጋሩ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ተመልሰው ይቀይሩ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ተደራሽነት"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"የቁልፍ ሰሌዳ አቋራጮች"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"የፍለጋ አቋራጮች"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ምንም የፍለጋ ውጤቶች የሉም"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"መሰብሰቢያ አዶ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"መዘርጊያ አዶ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ወይም"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"የቤት ምልክት"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"የተግባር ቁልፍ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ተከናውኗል"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ጥሩ ሠርተዋል!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ወደኋላ ተመለስ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ወደኋላ ለመመለስ የመዳሰሻ ሰሌዳው ላይ የትኛውም ቦታ በሦስት ጣቶች ወደግራ ወይም ወደቀኝ ያንሸራትቱ።\n\nእንዲሁም የቁልፍ ሰሌዳ አቋራጭ + ESC ለዚህ መጠቀም ይችላሉ።"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ወደ መነሻ ሂድ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"በማንኛውም ጊዜ ወደ መነሻ ማያ ገፅዎ ለመሄድ ከማያ ገፅዎ ታች በሦስት ጣቶች ወደላይ ያሸብልሉ።"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ሦስት ጣቶች ወደቀኝ እና ግራ ሲንቀሳቀሱ የሚያሳይ የመዳሰሻ ሰሌዳ"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"የኋላ ምልክት እነማ የሚያሳይ የመሣሪያ ማያ ገፅ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"የቁልፍ ሰሌዳ የጀርባ ብርሃን"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ደረጃ %1$d ከ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"የቤት ውስጥ ቁጥጥሮች"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ወደ መነሻ ለመሄድ የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"የቅርብ ጊዜ መተግበሪያዎችን ለማየት የመዳሰሻ ሰሌዳው ላይ በሦስት ጣቶች ወደላይ ያንሸራትቱ እና ይያዙ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ሁሉንም መተግበሪያዎችዎን ለማየት በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ጽሁፍ ተቀይሯል"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ለመመልከት ይክፈቱ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ሦስት ጣቶችን በመጠቀም ወደ ግራ ወይም ወደ ቀኝ ያንሸራትቱ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ወደ መነሻ ለመመለስ የመዳሰሻ ሰሌዳዎን ይጠቀሙ"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ እና ይያዙ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ሁሉንም መተግበሪያዎች ለማየት የቁልፍ ሰሌዳዎን ይጠቀሙ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"በማንኛውም ጊዜ የተግባር ቁልፍን ይጫኑ። ምልክቶችን የበለጠ ለማወቅ መታ ያድርጉ።"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ተጨማሪ ደብዛዛ አሁን የብሩህነት አሞሌ ክፍል ነው"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"አሁን ከማያ ገፅዎ በላይ የብሩህነት ደረጃውን ይበልጥ በመቀነስ ማያ ገፁን ተጨማሪ ደብዛዛ ማድረግ ይችላሉ።\n\nይህ በጨለማ አካባቢ ውስጥ ሲሆኑ በተሻለ ይሠራል።"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ተጨማሪ ደብዛዛ አቋራጭን አስወግድ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"የተጨማሪ ደብዛዛ አቋራጭን ያስወግዱ። የእርስዎን ብሩሃማነት ለመቀነስ መደበኛ የብሩሃማነት አሞሌውን ይጠቀሙ።"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 3b65cd84d595..1ccc3ebfd98f 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"مسجّل الشاشة"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"هل تريد بدء التسجيل؟"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"أثناء التسجيل، يمكن لنظام Android الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"أثناء تسجيل محتوى تطبيق، يمكن لنظام Android الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"بدء التسجيل"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"تسجيل الصوت"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"صوت الجهاز"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"الصوت من جهازك، مثلاً الموسيقى والمكالمات ونغمات الرنين"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"إرسال"</string> <string name="cancel" msgid="1089011503403416730">"إلغاء"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"شعار التطبيق"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"تأكيد"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"إعادة المحاولة"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"انقر لإلغاء المصادقة."</string> @@ -247,7 +255,7 @@ <string name="data_connection_roaming" msgid="375650836665414797">"التجوال"</string> <string name="cell_data_off" msgid="4886198950247099526">"غير مفعّلة"</string> <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string> - <string name="accessibility_vpn_on" msgid="8037549696057288731">"الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string> + <string name="accessibility_vpn_on" msgid="8037549696057288731">"شبكة VPN قيد التفعيل."</string> <string name="accessibility_battery_level" msgid="5143715405241138822">"مستوى البطارية <xliff:g id="NUMBER">%d</xliff:g> في المائة."</string> <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"نسبة شحن البطارية <xliff:g id="PERCENTAGE">%1$d</xliff:g> في المئة، <xliff:g id="TIME">%2$s</xliff:g>."</string> <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"جارٍ شحن البطارية، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"انقر لإقران جهاز جديد"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"تعذَّر تعديل الإعداد المسبق"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"الإعدادات المسبقة"</string> - <string name="live_caption_title" msgid="8916875614623730005">"النسخ النصي التلقائي"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"النسخ النصي التلقائي"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"هل تريد إزالة حظر ميكروفون الجهاز؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"هل تريد إزالة حظر كاميرا الجهاز؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"هل تريد إزالة حظر الكاميرا والميكروفون؟"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"الإعدادات"</string> <string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string> <string name="zen_mode_off" msgid="1736604456618147306">"غير مفعَّل"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"إعداد"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"الإدارة في الإعدادات"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ما مِن أوضاع مفعَّلة}=1{الوضع \"{mode}\" مفعَّل}two{وضعان مفعَّلان}few{# أوضاع مفعَّلة}many{# وضعًا مفعَّلاً}other{# وضع مفعَّل}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات والتذكيرات والأحداث والمتصلين الذين تحددهم. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"تخصيص"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن ببطء • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"التطبيقات المصغّرة على شاشة القفل"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"تمت إضافة تطبيق \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" المصغّر إلى شاشة القفل"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"تخصيص"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"إغلاق"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"سيتمكن تطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" من الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك أثناء التسجيل أو البثّ. ويشمل ذلك معلومات، مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"هل تريد بدء التسجيل أو البثّ؟"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ستتمكن الخدمة التي تقدّم هذه الوظيفة من الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك أثناء التسجيل أو البثّ. ويشمل ذلك معلومات، مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"الشاشة بالكامل"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"تطبيق واحد"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"مشاركة أو تسجيل محتوى تطبيق محدّد"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"هل تريد بدء التسجيل أو البثّ باستخدام \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"؟"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"أثناء المشاركة أو التسجيل أو البثّ، يمكن لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهاز، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثّه، يمكن لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"بدء"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"هل تريد مشاركة الشاشة مع تطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"؟"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"مشاركة تطبيق واحد"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"مشاركة الشاشة بأكملها"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"أثناء مشاركة محتوى الشاشة بالكامل، سيكون كل المحتوى المعروض على شاشتك مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"أثناء مشاركة محتوى تطبيق، سيكون كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"مشاركة الشاشة"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"تم إيقاف هذا الخيار من خلال تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"هل تريد بدء البثّ؟"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"أثناء البثّ، يمكن لنظام Android الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"أثناء بثّ محتوى تطبيق، يمكن لنظام Android الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"بدء البثّ"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"هل تريد بث محتوى الشاشة؟"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"بث محتوى تطبيق واحد"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"بث محتوى الشاشة بالكامل"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"أثناء بث محتوى الشاشة بالكامل، سيكون كل المحتوى المعروض على شاشتك مرئيًا. لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"أثناء بث محتوى تطبيق، سيكون كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق مرئيًا. لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"بث محتوى الشاشة"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"هل تريد بدء المشاركة؟"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"أثناء المشاركة أو التسجيل أو البثّ، يمكن لنظام Android الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثّه، يمكن لنظام Android الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"بدء"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"التالي"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"تتوقف المشاركة مؤقتًا عند التبديل بين التطبيقات."</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"مشاركة هذا التطبيق بدلاً من ذلك"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"الرجوع"</string> @@ -577,19 +589,19 @@ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال <xliff:g id="VPN_APP">%2$s</xliff:g>."</string> <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"هذا الجهاز يخص مؤسستك."</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>."</string> - <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"ينتمي هذا الجهاز إلى مؤسستك، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string> - <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال خدمات الشبكة الافتراضية الخاصة (VPN)."</string> + <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"ينتمي هذا الجهاز إلى مؤسستك، ويتّصل بالإنترنت من خلال خدمات شبكة VPN."</string> + <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"ينتمي هذا الجهاز إلى <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>، ويتّصل بالإنترنت من خلال خدمات شبكة VPN."</string> <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في ملف العمل"</string> <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملف العمل الخاص بك"</string> <string name="quick_settings_disclosure_managed_profile_network_activity" msgid="2636594621387832827">"تكون أنشطة شبكة ملف العمل مرئية لمشرف تكنولوجيا المعلومات."</string> <string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"قد تكون الشبكة خاضعة للمراقبة"</string> - <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"هذا الجهاز متّصل بالإنترنت من خلال خدمات الشبكات الافتراضية الخاصة (VPN)."</string> + <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"هذا الجهاز متّصل بالإنترنت من خلال خدمات شبكات VPN."</string> <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>."</string> <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"تطبيقاتك الشخصية متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>."</string> <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>."</string> <string name="monitoring_title_financed_device" msgid="3659962357973919387">"توفر مؤسسة \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\" هذا الجهاز"</string> <string name="monitoring_title_device_owned" msgid="7029691083837606324">"إدارة الأجهزة"</string> - <string name="monitoring_subtitle_vpn" msgid="800485258004629079">"شبكة افتراضية خاصة (VPN)"</string> + <string name="monitoring_subtitle_vpn" msgid="800485258004629079">"شبكة VPN"</string> <string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"تسجيل بيانات الشبكة"</string> <string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"شهادات CA"</string> <string name="monitoring_button_view_policies" msgid="3869724835853502410">"عرض السياسات"</string> @@ -605,12 +617,12 @@ <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". ويمكن لمقدِّم شبكة VPN الاطّلاع على أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفّح."</string> <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"هذا الجهاز متّصل بالإنترنت من خلال \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". تجدر الإشارة إلى أنّ أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، مرئية لمشرف تكنولوجيا المعلومات في مؤسستك."</string> <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"هذا الجهاز متّصل بالإنترنت من خلال <xliff:g id="VPN_APP_0">%1$s</xliff:g> و<xliff:g id="VPN_APP_1">%2$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات رؤية أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات ومزوّد خدمة الشبكة الافتراضية الخاصة (VPN) رؤية أنشطة الشبكة في تطبيقات العمل، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> - <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"تطبيقاتك الشخصية متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. تظهر أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمزوّد خدمة الشبكة الافتراضية الخاصة (VPN)."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"تطبيقات العمل الخاصة بك متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. يمكن لمشرف تكنولوجيا المعلومات ومزوّد خدمة شبكة VPN رؤية أنشطة الشبكة في تطبيقات العمل، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح."</string> + <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"تطبيقاتك الشخصية متّصلة بالإنترنت من خلال <xliff:g id="VPN_APP">%1$s</xliff:g>. تظهر أنشطة الشبكة، بما في ذلك الرسائل الإلكترونية وبيانات التصفُّح، لمزوّد خدمة شبكة VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"فتح إعدادات شبكة VPN"</string> <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"يتولّى أحد الوالدين إدارة هذا الجهاز. يمكن للوالدين عرض وإدارة معلوماتك، مثلاً التطبيقات التي تستخدمها وموقعك الجغرافي ووقت النظر إلى الشاشة."</string> - <string name="legacy_vpn_name" msgid="4174223520162559145">"شبكة افتراضية خاصة"</string> + <string name="legacy_vpn_name" msgid="4174223520162559145">"شبكة VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"فتح القفل باستمرار بواسطة TrustAgent"</string> <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"تم قفل الجهاز بسبب إجراء العديد من محاولات المصادقة"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"تم قفل الجهاز\nتعذّرت المصادقة"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"تسهيل الاستخدام"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"اختصارات لوحة المفاتيح"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"اختصارات طلبات البحث"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ما مِن نتائج بحث"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"رمز التصغير"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"رمز التوسيع"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"أو"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"إيماءة الانتقال إلى الشاشة الرئيسية"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"مفتاح الإجراء"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تم"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"أحسنت."</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"رجوع"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"لوحة لمس تعرض ثلاثة أصابع تتحرك يمينًا ويسارًا"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"شاشة جهاز تعرض صورة متحركة لإيماءة الرجوع"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"للرجوع، مرِّر سريعًا لليمين أو لليسار باستخدام ثلاثة أصابع في أي مكان على لوحة اللمس.\n\nيمكنك أيضًا الرجوع باستخدام اختصار لوحة المفاتيح \"مفتاح الإجراء + ESC\"."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"أحسنت"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"لقد أكملت التدريب على إيماءة الرجوع."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"الانتقال إلى الشاشة الرئيسية"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"للانتقال إلى الشاشة الرئيسية في أي وقت، مرِّر سريعًا من أسفل الشاشة إلى أعلاها بثلاثة أصابع."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"أحسنت"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"لقد أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"مفتاح الإجراء"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"للوصول إلى التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"تهانينا!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"لقد أكملت التدريب على إيماءة مفتاح الإجراء.\n\nيؤدي الضغط على مفتاح الإجراء + / إلى عرض جميع الاختصارات المتاحة."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"مستوى الإضاءة: %1$d من %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"إدارة المنزل آليًّا"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"للانتقال إلى الشاشة الرئيسية، مرِّر سريعًا للأعلى على لوحة اللمس باستخدام 3 أصابع"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"لعرض التطبيقات المستخدَمة مؤخرًا، مرِّر سريعًا للأعلى مع استمرار الضغط على لوحة اللمس باستخدام 3 أصابع"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"لعرض جميع التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"إشعار مخفي"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"افتح القفل لعرض المعلومات"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"استخدِم لوحة اللمس للرجوع"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"مرِّر سريعًا لليمين أو لليسار باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"استخدِم لوحة اللمس للانتقال إلى الشاشة الرئيسية"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"مرِّر سريعًا للأعلى مع استمرار الضغط باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"استخدِم لوحة المفاتيح لعرض جميع التطبيقات"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"اضغط على مفتاح الإجراء في أي وقت. انقر للتعرّف على المزيد من الإيماءات."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ميزة \"زيادة تعتيم الشاشة\" أصبحت الآن ضمن شريط مستوى السطوع"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"يمكنك الآن زيادة تعتيم الشاشة عن طريق خفض مستوى السطوع بشكل أكبر من أعلى الشاشة.\n\nيُعد هذا الخيار مناسبًا عندما تكون في مكان مظلم."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"إزالة اختصار \"زيادة تعتيم الشاشة\""</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"تمت إزالة اختصار \"زيادة تعتيم الشاشة\". لخفض مستوى سطوع شاشتك، استخدِم شريط مستوى السطوع العادي."</string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 576e8ad2b252..9b2b92408fe9 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ৰেকৰ্ড কৰা আৰম্ভ কৰিবনে?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"আপুনি ৰেকৰ্ড কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"আপুনি এটা এপ্ ৰেকৰ্ড কৰাৰ সময়ত সেইটো এপত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ৰেকৰ্ডিং আৰম্ভ কৰক"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিঅ’ ৰেকৰ্ড কৰক"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ডিভাইচৰ অডিঅ’"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"সংগীত, কল আৰু ৰিংট’নসমূহৰ দৰে আপোনাৰ ডিভাইচৰ পৰা কেপচাৰ কৰিব পৰা ধ্বনি"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"পঠিয়াওক"</string> <string name="cancel" msgid="1089011503403416730">"বাতিল কৰক"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"এপৰ ল’গ’"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"নিশ্চিত কৰক"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"আকৌ চেষ্টা কৰক"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ বাতিল কৰিবলৈ টিপক"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইচ পেয়াৰ কৰিবলৈ ক্লিক কৰক"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্ৰিছেট আপডে’ট কৰিব পৰা নগ’ল"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"প্ৰিছেট"</string> - <string name="live_caption_title" msgid="8916875614623730005">"লাইভ কেপশ্বন"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"লাইভ কেপশ্বন"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইচৰ মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইচৰ কেমেৰা অৱৰোধৰ পৰা আঁতৰাবনে?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইচৰ কেমেৰা আৰু মাইক্ৰ\'ফ\'ন অৱৰোধৰ পৰা আঁতৰাবনে?"</string> @@ -475,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • লাহে লাহে চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্ৰীনত ৱিজেট"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেট লক স্ক্ৰীনত যোগ দিয়া হৈছে"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাষ্টমাইজ কৰক"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"অগ্ৰাহ্য কৰক"</string> @@ -528,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকৰ্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে’ কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, ফট’, বাৰ্তাসমূহ আৰু আপুনি প্লে’ কৰা অডিঅ’ৰ দৰে তথ্য অন্তৰ্ভুক্ত হয়।"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ৰেকৰ্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকৰ্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে’ কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, ফট’, বাৰ্তাসমূহ আৰু আপুনি প্লে’ কৰা অডিঅ’ৰ দৰে তথ্য অন্তৰ্ভুক্ত হয়।"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"সম্পূৰ্ণ স্ক্ৰীন"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"এটা একক এপ্"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"এটা এপ্ শ্বেয়াৰ অথবা ৰেকৰ্ড কৰক"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ জৰিয়তে ৰেকৰ্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"আৰম্ভ কৰক"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ সৈতে আপোনাৰ স্ক্ৰীন শ্বেয়াৰ কৰিবনে?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"এটা এপ্ শ্বেয়াৰ কৰক"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰক"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপুনি আপোনাৰ গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰি থাকোঁতে, আপোনাৰ স্ক্ৰীনত থকা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"আপুনি কোনো এপ্ শ্বেয়াৰ কৰি থাকোঁতে সেই এপ্টোত দেখুওৱা বা প্লে’ কৰা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্ৰীন শ্বেয়াৰ কৰক"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ এই বিকল্পটো অক্ষম কৰিছে"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"কাষ্ট কৰিবলৈ আৰম্ভ কৰিবনে?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"আপুনি কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"আপুনি এটা এপ্ কাষ্ট কৰাৰ সময়ত সেইটো এপত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"কাষ্ট কৰিবলৈ আৰম্ভ কৰক"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"আপোনাৰ স্ক্ৰীনখন কাষ্ট কৰিবনে?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"এটা এপ্ কাষ্ট কৰক"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"গোটেই স্ক্ৰীনখন কাষ্ট কৰক"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"যেতিয়া আপুনি গোটেই স্ক্ৰীনখন কাষ্ট কৰি থাকে, তেতিয়া আপোনাৰ স্ক্ৰীনত থকা যিকোনো বস্তু দৃশ্যমান হয়। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"যেতিয়া আপুনি কোনো এপ্ কাষ্ট কৰি থাকে, তেতিয়া সেই এপ্টোত দেখুওৱা বা প্লে’ কৰা যিকোনো বস্তু দৃশ্যমান হয়। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"স্ক্ৰীন কাষ্ট কৰক"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"শ্বেয়াৰ কৰিবলৈ আৰম্ভ কৰিবনে?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"আৰম্ভ কৰক"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"পৰৱৰ্তী"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"আপুনি এপ্ সলনি কৰিলে শ্বেয়াৰ কৰাটো পজ হয়"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"তাৰ সলনি এই এপ্টো শ্বেয়াৰ কৰক"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"উভতি যাওক"</string> @@ -1373,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"সাধ্য সুবিধা"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"কীব’ৰ্ডৰ শ্বৰ্টকাট"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"সন্ধানৰ শ্বৰ্টকাট"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"সন্ধানৰ কোনো ফলাফল নাই"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"সংকোচন কৰাৰ চিহ্ন"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"বিস্তাৰ কৰাৰ চিহ্ন"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string> @@ -1380,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"কাৰ্য কী"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হ’ল"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"বঢ়িয়া!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"উভতি যাওক"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"তিনিটা আঙুলি সোঁ আৰু বাওঁফালে লৰচৰ কৰা দেখুওৱা টাচ্চপেড"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"পিছফালৰ নিৰ্দেশৰ এনিমেশ্বন দেখুওৱা ডিভাইচ স্ক্ৰীন"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"উভতি যাবলৈ, টাচ্চপেডৰ যিকোনো স্থানত তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁ বা সোঁফালে ছোৱাইপ কৰক।\n\nইয়াৰ বাবে আপুনি কীব’ৰ্ড শ্বৰ্টকাট কাৰ্য + ESC ব্যৱহাৰ কৰিবও পাৰে।"</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"বঢ়িয়া!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"আপুনি উভতি যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"গৃহ পৃষ্ঠালৈ যাওক"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"যিকোনো সময়তে আপোনাৰ গৃহ স্ক্ৰীনলৈ যাবলৈ, আপোনাৰ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ তিনিটা আঙুলিৰে ছোৱাইপ কৰক।"</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"সুন্দৰ!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"আপুনি গৃহ স্ক্ৰীনলৈ উভতি যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"কাৰ্য কী"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"আপোনাৰ এপ্সমূহ এক্সেছ কৰিবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক।"</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"অভিনন্দন!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"আপুনি কাৰ্য কীৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।\n\nকাৰ্য + /এ আপোনাৰ বাবে উপলব্ধ আটাইবোৰ শ্বৰ্টকাট দেখুৱায়।"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীব’ৰ্ডৰ বেকলাইট"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dৰ %1$d স্তৰ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ"</string> @@ -1397,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"গৃহপৃষ্ঠালৈ যাওক, টাচ্চপেডত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰক"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"শেহতীয়া এপ্সমূহ চাবলৈ টাচ্চপেডখনত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপোনাৰ আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"সম্পাদনা কৰা হৈছে"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"চাবলৈ আনলক কৰক"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"উভতি যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁফাললৈ বা সোঁফাললৈ ছোৱাইপ কৰক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"গৃহপৃষ্ঠালৈ যাবলৈ আপোনাৰ টাচ্চপেড ব্যৱহাৰ কৰক"</string> @@ -1405,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ড ব্যৱহাৰ কৰক"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"যিকোনো সময়তে কাৰ্য কীটোত টিপক। অধিক নিৰ্দেশ শিকিবলৈ টিপক।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"এক্সট্ৰা ডিম এতিয়া উজ্জ্বলতা বাৰৰ অংশ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"আপুনি এতিয়া আপোনাৰ স্ক্ৰীনৰ একেবাৰে ওপৰৰ পৰা উজ্জ্বলতাৰ স্তৰ আৰু অধিক হ্ৰাস কৰি স্ক্ৰীনখন এক্সট্ৰা ডিম কৰিব পাৰে।\n\nআপুনি অন্ধকাৰ পৰিৱেশত থাকিলে এই সুবিধাটোৱে আটাইতকৈ ভাল কাম কৰে।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"এক্সট্ৰা ডিম শ্বৰ্টকাট আঁতৰাওক"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"এক্সট্ৰা ডিম শ্বৰ্টকাট আঁতৰোৱা হৈছে। আপোনাৰ উজ্জ্বলতা হ্ৰাস কৰিবলৈ, নিয়মীয়া উজ্জ্বলতা বাৰ ব্যৱহাৰ কৰক।"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index d6abf079a2c0..9006f5987dc1 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekran yazıcısı"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Qeydəalma başladılsın?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Qeydə aldıqda Android-in ekranda görünən və ya cihazda oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Tətbiq qeydə aldıqda Android-in həmin tətbiqdə göstərilən və ya oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Qeydə almağa başlayın"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio yazın"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Cihaz audiosu"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Cihazınızdan gələn musiqi, zənglər və zəng melodiyaları kimi səslər"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Göndərin"</string> <string name="cancel" msgid="1089011503403416730">"Ləğv edin"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Tətbiq loqosu"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Təsdiq"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Yenidən cəhd edin"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Doğrulanmanı ləğv etmək üçün toxunun"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz birləşdirmək üçün klikləyin"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncəllənmədi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Hazır Ayar"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Avtomatik subtitrlər"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Avtomatik subtitrlər"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonu blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerası blokdan çıxarılsın?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası və mikrofonu blokdan çıxarılsın?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Deaktiv"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Ayarlayın"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Ayarlarda idarə edin"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aktiv rejim yoxdur}=1{{mode} aktivdir}other{# rejim aktivdir}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Seçdiyiniz siqnal, xatırladıcı, tədbir və zənglər istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Siqnallar istisna olmaqla səslər və vibrasiyalar Sizi narahat etməyəcək. Musiqi, video və oyunlar da daxil olmaqla oxutmaq istədiyiniz hər şeyi eşidəcəksiniz."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Fərdiləşdirin"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Asta şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilid ekranındakı vidcetlər"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti kilid ekranına əlavə edildi"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Fərdiləşdirin"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Bağlayın"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> qeydəalma və ya yayım zamanı ekranda görünən, yaxud cihazda oxudulan məlumatlara giriş edə biləcək. Bura parol, ödəniş detalları, foto, mesaj və oxudulan audio kimi məlumatlar daxildir."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Qeydəalma və ya yayım başladılsın?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyanı təmin edən xidmətin qeydəalma və ya yayım zamanı ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olacaq. Bura parol, ödəniş detalları, foto, mesaj və oxudulan audio kimi məlumatlar daxildir."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Bütün ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Tək tətbiq"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Tətbiq paylaşın və ya qeydə alın"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə qeydəalma və ya yayım başladılsın?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Paylaşım, qeydəalma və ya yayım zamanı <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ekranda görünən, yaxud cihazda oxudulan məlumatlara giriş edə bilir. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Tətbiq paylaşdıqda, qeydə aldıqda və ya yayımladıqda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> həmin tətbiqdə göstərilən, yaxud oxudulan məlumatlara giriş edə bilir. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Başlayın"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekran <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə paylaşılsın?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bir tətbiq paylaşın"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bütün ekranı paylaşın"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Bütün ekranı paylaşdığınız zaman ekrandakı hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Tətbiq paylaşdığınız zaman həmin tətbiqdə göstərilən və ya işə salınan hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaşın"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu seçimi deaktiv edib"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Yayım başladılsın?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Yayım zamanı Android-in ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Tətbiq yayımladıqda Android-in həmin tətbiqdə göstərilən və ya oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Yayıma başlayın"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Ekran yayımlansın?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Bir tətbiqi yayımlayın"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Bütün ekranı yayımlayın"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Bütün ekranı yayımladıqda ekrandakı hər şey görünür. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Tətbiq yayımladıqda həmin tətbiqdə göstərilən və ya işə salınan hər şey görünür. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Ekranı yayımlayın"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Paylaşım başladılsın?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Paylaşım, qeydəalma və ya yayım zamanı Android-in ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Tətbiq paylaşdıqda, qeydə aldıqda və ya yayımladıqda Android-in həmin tətbiqdə göstərilən, yaxud oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Başlayın"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Növbəti"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Tətbiqləri dəyişdikdə paylaşım durdurulur"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Bu tətbiqi paylaşın"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Geri dəyişin"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Xüsusi imkanlar"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klaviatura qısayolları"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Axtarış qısayolları"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Axtarış nəticəsi yoxdur"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"İkonanı yığcamlaşdırın"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"İkonanı genişləndirin"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"və ya"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Əsas ekran jesti"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Əməliyyat düyməsi"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hazırdır"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Əla!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri qayıdın"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Geri getmək üçün taçpeddə istənilən yerdə üç barmaqla sola və ya sağa çəkin.\n\nBunun üçün Action + ESC klaviatura qısayolundan da istifadə edə bilərsiniz."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ana ekrana qayıdın"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"İstənilən vaxt ana ekrana keçmək üçün ekranın aşağısından üç barmağınızla yuxarı çəkin."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Üç barmağın sağa və sola hərəkət etdiyini göstərən taçped"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri jesti üçün animasiya göstərən cihaz ekranı"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura işığı"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Səviyyə %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev nizamlayıcıları"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana səhifəyə keçmək üçün taçpeddə üç barmağınızla yuxarı çəkin"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son tətbiqlərə baxmaq üçün taçpeddə üç barmağınızla yuxarı çəkib saxlayın"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bütün tətbiqlərə baxmaq üçün klaviaturada fəaliyyət açarını basın"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Çıxarılıb"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Baxmaq üçün kiliddən çıxarın"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri qayıtmaq üçün taçped istifadə edin"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç barmaqla sola və ya sağa çəkin. Daha çox jest öyrənmək üçün toxunun."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana səhifəyə keçmək üçün taçped istifadə edin"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç barmaq ilə yuxarı çəkib saxlayın. Daha çox jest öyrənmək üçün toxunun."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bütün tətbiqlərə baxmaq üçün klaviatura istifadə edin"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstənilən vaxt fəaliyyət açarını basın. Daha çox jest öyrənmək üçün toxunun."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Əlavə qaraltma artıq parlaqlıq panelinin bir hissəsidir"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"İndi ekranın yuxarısında parlaqlıq səviyyəsini daha da aşağı salaraq ekranı əlavə qaralda bilərsiniz.\n\nTünd mühitdə olduqda nəticə yaxşı olur."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Əlavə qaraltma qısayolunu silin"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Əlavə qaraltma qısayolu silindi. Parlaqlığı aşağı salmaq üçün adi parlaqlıq panelindən istifadə edin."</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 307dcc097aec..85e1773d82ff 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Želite da započnete snimanje?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju dok snimate. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kada snimate aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Započni snimanje"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimaj zvuk"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk uređaja"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk sa uređaja, na primer, muzika, pozivi i melodije zvona"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string> <string name="cancel" msgid="1089011503403416730">"Otkaži"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotip aplikacije"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdi"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Probaj ponovo"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da biste otkazali potvrdu identiteta"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili nov uređaj"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadatih podešavanja nije uspelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Unapred određena podešavanja"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Titl uživo"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Titl uživo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite da odblokirate mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite da odblokirate kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite da odblokirate kameru i mikrofon uređaja?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Podešavanja"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Podesi"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte u podešavanjima"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih režima}=1{Aktivan je {mode} režim}one{Aktivan je # režim}few{Aktivna su # režima}other{Aktivno je # režima}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas uznemiravati zvukovi i vibracije osim za alarme, podsetnike, događaje i pozivaoce koje navedete. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas uznemiravati zvukovi i vibracije osim za alarme. I dalje ćete čuti sve što odaberete da pustite, uključujući muziku, video snimke i igre."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prilagodi"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo se puni • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> je dodat na zaključani ekran"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Želite da počnete snimanje ili prebacivanje?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Ceo ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikacija"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Delite ili snimite aplikaciju"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Želite da počnete snimanje ili prebacivanje pomoću aplikacije <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada delite, snimate ili prebacujete, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kada delite, snimate ili prebacujete aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite da delite ekran sa aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli jednu aplikaciju"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli ceo ekran"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada delite ceo ekran, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sve što je na njemu. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada delite aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sav sadržaj koji se prikazuje ili pušta u njoj. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli ekran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućila ovu opciju"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite da započnete prebacivanje?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Započni prebacivanje"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Želite da prebacite ekran?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Prebaci jednu aplikaciju"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Prebaci ceo ekran"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kada prebacujete ceo ekran, vidi se sve što je na njemu. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kada prebacujete aplikaciju, vidi se sav sadržaj koji se prikazuje ili pušta u njoj. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Prebacivanje ekrana"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Želite da počnete da delite?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kada delite, snimate ili prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kada delite, snimate ili prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, i audio i video sadržaj."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Pokreni"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Dalje"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Deljenje se zaustavlja kada menjate aplikacije"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Deli ovu aplikaciju"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Vrati"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pristupačnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tasterske prečice"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Prečice pretrage"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nema rezultata pretrage"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za skupljanje"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za početnu stranicu"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Taster radnji"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da biste se vratili, prevucite ulevo sa tri prsta bilo gde na tačpedu.\n\nMožete da koristite i tastersku prečicu Alt + ESC za ovo."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Idi na početni ekran"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da biste otišli na početni ekran u bilo kom trenutku, prevucite nagore od dna ekrana pomoću tri prsta."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tačped sa prikazom tri prsta koji se pomeraju udesno i ulevo"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja sa prikazom animacije pokreta za nazad"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvetljenje tastature"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste otišli na početni ekran, prevucite nagore sa tri prsta na tačpedu"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da biste pregledali nedavne aplikacije, prevucite nagore i zadržite sa tri prsta na tačpedu"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da biste pogledali sve aplikacije, pritisnite taster radnji na tastaturi"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redigovano"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte za prikaz"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite tačped da biste se vratili"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulevo ili udesno sa tri prsta. Dodirnite da biste videli više pokreta."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite tačped da biste otišli na početni ekran"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite sa tri prsta. Dodirnite da biste videli više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da biste pregledali sve aplikacije"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite taster radnji u bilo kom trenutku. Dodirnite da biste videli više pokreta."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjivanje je sada deo trake za osvetljenost"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sada možete dodatno da zatamnite ekran smanjivanjem nivoa osvetljenosti pri vrhu ekrana. \n\nOvo najbolje funkcioniše kada ste u tamnom okruženju."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečicu za dodatno zatamnjivanje"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Uklonjena je prečica za dodatno zatamnjivanje. Da biste smanjili osvetljenost, koristite uobičajenu traku za osvetljenost."</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 0580d7ebb4a5..d782bb2bd889 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -50,8 +50,8 @@ <string name="always_use_device" msgid="210535878779644679">"Заўсёды адкрываць <xliff:g id="APPLICATION">%1$s</xliff:g>, калі падключана прылада <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string> <string name="always_use_accessory" msgid="1977225429341838444">"Заўсёды адкрываць <xliff:g id="APPLICATION">%1$s</xliff:g>, калі падключаны аксесуар <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string> <string name="usb_debugging_title" msgid="8274884945238642726">"Дазволіць адладку па USB?"</string> - <string name="usb_debugging_message" msgid="5794616114463921773">"Адбiтак ключа RSA на гэтым камп\'ютары:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> - <string name="usb_debugging_always" msgid="4003121804294739548">"Заўсёды дазваляць з гэтага камп\'ютара"</string> + <string name="usb_debugging_message" msgid="5794616114463921773">"Адбiтак ключа RSA на гэтым камп’ютары:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> + <string name="usb_debugging_always" msgid="4003121804294739548">"Заўсёды дазваляць з гэтага камп’ютара"</string> <string name="usb_debugging_allow" msgid="1722643858015321328">"Дазволіць"</string> <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Адладка па USB забаронена"</string> <string name="usb_debugging_secondary_user_message" msgid="1888835696965417845">"Карыстальнік, які зараз увайшоў у гэтую прыладу, не можа ўключыць адладку цераз USB. Каб выкарыстоўваць гэтую функцыю, пераключыцеся на адміністратара."</string> @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Запіс экрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Пачаць запіс?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Калі адбываецца запіс, Android мае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Калі адбываецца запіс змесціва праграмы, Android мае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Пачаць запіс"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Запісаць аўдыя"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Аўдыя з прылады"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Гук на вашай прыладзе, напрыклад музыка, выклікі і рынгтоны"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Адправіць"</string> <string name="cancel" msgid="1089011503403416730">"Скасаваць"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Лагатып праграмы"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Пацвердзіць"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Паўтарыць спробу"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Націсніце, каб скасаваць аўтэнтыфікацыю"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Націсніце, каб спалучыць новую прыладу"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не ўдалося абнавіць набор налад"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набор налад"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Аўтаматычныя субцітры"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Аўтаматычныя субцітры"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблакіраваць мікрафон прылады?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблакіраваць камеру прылады?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблакіраваць камеру і мікрафон прылады?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налады"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Выключана"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Наладзіць"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Адкрыць налады"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Актыўных рэжымаў няма}=1{Рэжым \"{mode}\" актыўны}one{# рэжым актыўны}few{# рэжымы актыўныя}many{# рэжымаў актыўныя}other{# рэжыму актыўныя}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў, напамінаў, падзей і выбраных вамі абанентаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Дапасаваць"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе павольная зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджэты на экране блакіроўкі"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" дададзены на экран блакіроўкі"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Наладзіць"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыць"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Падчас запісу ці трансляцыі праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэтая інфармацыя ўключае паролі, звесткі пра аплату, фота, паведамленні і аўдыя, якое вы прайграяце."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Пачаць запіс або трансляцыю?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Падчас запісу ці трансляцыі служба, якая забяспечвае работу гэтай функцыі, будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэтая інфармацыя ўключае паролі, плацежных рэквізітаў, фота, паведамленні і аўдыя, якое вы прайграяце."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Увесь экран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Адна праграма"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Абагульванне або запіс праграмы"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Пачаць запіс або трансляцыю з дапамогай праграмы \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Калі пачынаецца абагульванне, запіс ці трансляцыя, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> атрымлівае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Калі пачынаецца абагульванне, запіс ці трансляцыя змесціва праграмы, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> атрымлівае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Пачаць"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Абагуліць экран з праграмай \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Абагуліць адну праграму"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Абагуліць увесь экран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Калі вы абагульваеце ўвесь экран, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што адбываецца на экране. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Калі вы абагульваеце праграму, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што паказваецца ці прайграецца ў гэтай праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Абагуліць экран"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" адключыла гэты параметр"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Пачаць трансляцыю?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Калі адбываецца трансляцыя, Android мае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Калі адбываецца трансляцыя змесціва праграмы, Android мае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Пачаць трансляцыю"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Уключыць трансляцыю экрана?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Трансліраваць адну праграму"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Трансліраваць увесь экран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Калі вы трансліруеце ўвесь экран, бачна ўсё, што адбываецца на экране. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Калі вы трансліруеце праграму, бачна ўсё, што паказваецца ці прайграецца ў гэтай праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Трансліраваць экран"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Пачаць абагульванне?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Калі адбываецца абагульванне, запіс ці трансляцыя, Android мае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Калі адбываецца абагульванне, запіс ці трансляцыя змесціва праграмы, Android мае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Пачаць"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Далей"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Пры пераключэнні праграм абагульванне прыпыняецца"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Абагуліць гэту праграму"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Пераключыцца назад"</string> @@ -741,10 +753,10 @@ <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Стан:</b> Пераведзена ў рэжым \"Без гуку\""</string> <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Стан:</b> Ацэнена як важнае"</string> <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Стан:</b> Ацэнена як няважнае"</string> - <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"З\'яўляецца ўверсе раздзела размоў і паказвае на экране блакіроўкі відарыс профілю"</string> - <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"З\'яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое паказвае на экране блакіроўкі відарыс профілю"</string> - <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"З\'яўляецца ўверсе раздзела размоў, перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string> - <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З\'яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string> + <string name="notification_channel_summary_priority_baseline" msgid="46674690072551234">"З’яўляецца ўверсе раздзела размоў і паказвае на экране блакіроўкі відарыс профілю"</string> + <string name="notification_channel_summary_priority_bubble" msgid="1275413109619074576">"З’яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое паказвае на экране блакіроўкі відарыс профілю"</string> + <string name="notification_channel_summary_priority_dnd" msgid="6665395023264154361">"З’яўляецца ўверсе раздзела размоў, перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string> + <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З’яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string> <string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string> <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не падтрымлівае функцыі размовы"</string> <string name="notification_unblockable_desc" msgid="2073030886006190804">"Гэтыя апавяшчэнні нельга змяніць."</string> @@ -1056,7 +1068,7 @@ <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Каб часова схаваць кнопку, перамясціце яе на край"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Адрабіць"</string> <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Кнопка спецыяльных магчымасцей схавана"</string> - <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Калі вы хочаце, каб яна з\'явілася, націсніце на апавяшчэнне"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Калі вы хочаце, каб яна з’явілася, націсніце на апавяшчэнне"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Выдалены ярлык <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Выдалены # ярлык}one{Выдалены # ярлык}few{Выдалена # ярлыкі}many{Выдалена # ярлыкоў}other{Выдалена # ярлыка}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перамясціць лявей і вышэй"</string> @@ -1210,7 +1222,7 @@ <string name="game_status" msgid="1340694320630973259">"Ідзе гульня"</string> <string name="empty_user_name" msgid="3389155775773578300">"Сябры"</string> <string name="empty_status" msgid="5938893404951307749">"Паразмаўляем у чаце!"</string> - <string name="status_before_loading" msgid="1500477307859631381">"Неўзабаве з\'явіцца змесціва"</string> + <string name="status_before_loading" msgid="1500477307859631381">"Неўзабаве з’явіцца змесціва"</string> <string name="missed_call" msgid="4228016077700161689">"Прапушчаны выклік"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> <string name="people_tile_description" msgid="8154966188085545556">"Глядзець нядаўнія паведамленні, прапушчаныя выклікі і абнаўленні стану"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Спецыяльныя магчымасці"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Спалучэнні клавіш"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Пошук спалучэнняў клавіш"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Няма вынікаў пошуку"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Згарнуць\""</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Разгарнуць\""</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жэст для вяртання на галоўны экран"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дзеяння"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Гатова"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Цудоўна!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Паказваецца, як на сэнсарнай панэлі тры пальцы рухаюцца ўправа і ўлева"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране прылады паказваецца анімацыя жэста \"Назад\""</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Каб вярнуцца, правядзіце трыма пальцамі ўлева ці ўправа ў любым месцы сэнсарнай панэлі.\n\nТаксама можна выкарыстоўваць спалучэнне \"клавіша дзеяння + ESC\"."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Выдатная праца!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Вы навучыліся рабіць жэст вяртання."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На галоўны экран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Каб у любы момант перайсці на галоўны экран, правядзіце па экране трыма пальцамі знізу ўверх."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Выдатна!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Вы навучыліся рабіць жэст для пераходу на галоўны экран."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Клавіша дзеяння"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Каб атрымаць доступ да праграм, націсніце клавішу дзеяння на клавіятуры."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Віншуем!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Вы навучыліся рабіць жэст з клавішай дзеяння.\n\nКалі націснуць клавішу дзеяння разам з \"/\", будуць паказаны ўсе даступныя спалучэнні клавіш."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Падсветка клавіятуры"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Узровень %1$d з %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Кіраванне домам"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Каб вярнуцца на галоўны экран, правядзіце па сэнсарнай панэлі трыма пальцамі ўверх"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Для прагляду нядаўніх праграм правядзіце па сэнсарнай панэлі трыма пальцамі ўверх і затрымайцеся"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Каб праглядзець усе праграмы, націсніце на клавішу дзеяння на клавіятуры"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Схавана"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Разблакіруйце экран, каб праглядзець"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Выкарыстайце сэнсарную панэль для вяртання"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Правядзіце ўлева ці ўправа трыма пальцамі. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Выкарыстайце сэнсарную панэль для вяртання на галоўны экран"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Правядзіце трыма пальцамі ўверх і затрымайце пальцы. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Выкарыстайце клавіятуру для прагляду ўсіх праграм"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Можна націснуць на клавішу дзеяння ў любы момант. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Цяпер кіраваць дадатковым памяншэннем яркасці можна на панэлі яркасці"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Цяпер вы можаце дадаткова зацямніць экран, яшчэ больш панізіўшы ўзровень яркасці праз налады ўверсе экрана.\n\nГэта функцыя працуе лепш за ўсё ў цёмным асяроддзі."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Выдаліць хуткую каманду для дадатковага памяншэння яркасці"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Хуткая каманда для дадатковага памяншэння яркасці выдалена. Каб паменшыць яркасць, выкарыстоўвайце звычайную панэль яркасці."</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index dfa9598a1062..423723e76da1 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Запис на екрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Искате ли да стартирате записване?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Когато записвате, Android има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Докато записвате дадено приложение, Android има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Стартиране на записването"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Записване на звук"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук от устройството"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук от устройството ви, като например музика, обаждания и мелодии"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Изпращане"</string> <string name="cancel" msgid="1089011503403416730">"Отказ"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Лого на приложението"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потвърждаване"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Нов опит"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Докоснете, за да анулирате удостоверяването"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за сдвояване на ново устройство"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Предварително зададените настройки не бяха актуализирани"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Предварително зададено"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Надписи на живо"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Надписи на живо"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се отблокира ли микрофонът на устройството?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се отблокира ли камерата на устройството?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се отблокират ли камерата и микрофонът на устройството?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string> <string name="zen_mode_off" msgid="1736604456618147306">"Изкл."</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Настройване"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Управление от настройките"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Няма активни режими}=1{Режимът „{mode}“ е активен}other{# активни режима}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници, напомняния, събития и обаждания от посочени от вас контакти. Пак ще чувате всичко, което изберете да се пусне, включително музика, видеоклипове и игри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Няма да бъдете обезпокоявани от звуци и вибрирания освен от будилници. Ще чувате обаче всичко, което изберете пуснете, включително музика, видеоклипове и игри."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Персонализиране"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се бавно • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Приспособления на заключения екран"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Приспособлението <xliff:g id="WIDGET_NAME">%1$s</xliff:g> бе добавено на заключения екран"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Персонализиране"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отхвърляне"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, подробности за начини на плащане, снимки, съобщения и възпроизвеждано аудио."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Искате ли да стартирате записване или предаване?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата, предоставяща тази функция, ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, подробности за начини на плащане, снимки, съобщения и възпроизвеждано аудио."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Цял екран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Едно приложение"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Споделяне или записване на приложение"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Искате ли да стартирате записване или предаване чрез <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Когато споделяте, записвате или предавате дадено приложение, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Стартиране"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели ли екранът ви с(ъс) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделяне на едно приложение"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделяне на целия екран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Когато споделяте целия си екран, всичко, което се показва на него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Когато споделяте приложение, всичко, което се показва или възпроизвежда в него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Споделяне на екрана"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> деактивира тази опция"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Искате ли да стартирате предаване?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Когато предавате, Android има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Когато предавате дадено приложение, Android има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Стартиране на предаването"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Искате ли да предавате екрана си?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Предаване на едно приложение"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Предаване на целия екран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Когато предавате целия екран, всичко, което се показва на него, е видимо. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Когато предавате дадено приложение, всичко, което се показва или възпроизвежда в него, е видимо. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Предаване на екрана"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Искате ли да стартирате споделяне?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Когато споделяте, записвате или предавате, Android има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Когато споделяте, записвате или предавате дадено приложение, Android има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Стартиране"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Напред"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Споделянето се поставя на пауза, когато превключвате приложенията"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Вместо това споделете приложението"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Превключване обратно"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Достъпност"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Клавишни комбинации"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Търсете клавишни комбинации"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Няма резултати от търсенето"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за свиване"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за разгъване"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест за преминаване към началния екран"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиш за действия"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"За да се върнете назад, прекарайте три пръста наляво или надясно по сензорния панел.\n\nЗа целта можете също да използвате комбинацията с клавиша за действия + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Към началния екран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"За да преминете към началния екран по всяко време, прекарайте три пръста нагоре от долната част на екрана."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сензорен панел, върху който три пръста се движат надясно и наляво"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран на устройство, показващ анимация за жеста за връщане назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка на клавиатурата"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d от %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за дома"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"За да преминете към началния екран, плъзнете нагоре по сензорния панел с три пръста"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да прегледате скорошните приложения, плъзнете нагоре по сензорния панел с три пръста и задръжте"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"За да прегледате всичките си приложения, натиснете клавиша за действия на клавиатурата си"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Скрито"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Отключете за преглед"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Използвайте сензорния панел, за да се върнете назад"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Плъзнете три пръста наляво или надясно. Докоснете, за да научите повече жестове."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Използвайте сензорния панел, за да преминете към началния екран"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Плъзнете нагоре с три пръста и задръжте. Докоснете, за да научите повече жестове."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Използвайте клавиатурата, за да прегледате всички приложения"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Натиснете клавиша за действия по всяко време. Докоснете, за да научите повече жестове."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Функцията за допълнителнително затъмняване вече е част от лентата за яркостта"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Вече можете да затъмнявате екрана допълнително, като намалявате яркостта още повече от лентата в горната му част.\n\nТова е най-полезно, когато сте на тъмно място."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Премахване на прекия път за допълнително затъмняване"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Прекият път за допълнително затъмняване е премахнат. За да намалите яркостта, използвайте обикновената лента за управлението ѝ."</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 3f6c26922bb4..f83b888fc4b1 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"স্ক্রিন রেকর্ডার"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"রেকর্ডিং শুরু করবেন?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"আপনি রেকর্ড করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"আপনি কোনও অ্যাপের মাধ্যমে রেকর্ড করার সময়, ওই অ্যাপে দেখানো বা চালানো হয় এমন সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো জিনিস সম্পর্কে সতর্ক থাকুন।"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"রেকর্ড করা শুরু করুন"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিও রেকর্ড করুন"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ডিভাইস অডিও"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"মিউজিক, কল এবং রিংটোনগুলির মতো আপনার ডিভাইস থেকে সাউন্ড"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"পাঠান"</string> <string name="cancel" msgid="1089011503403416730">"বাতিল করুন"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"অ্যাপের লোগো"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"কনফার্ম করুন"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"আবার চেষ্টা করুন"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"যাচাইকরণ বাতিল করতে ট্যাপ করুন"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"নতুন ডিভাইস পেয়ার করতে ক্লিক করুন"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্রিসেট আপডেট করা যায়নি"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"প্রিসেট"</string> - <string name="live_caption_title" msgid="8916875614623730005">"লাইভ ক্যাপশন"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"লাইভ ক্যাপশন"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ডিভাইসের মাইক্রোফোন আনব্লক করতে চান?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ডিভাইসের ক্যামেরা আনব্লক করতে চান?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ডিভাইসের ক্যামেরা এবং মাইক্রোফোন আনব্লক করতে চান?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"সেটিংস"</string> <string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string> <string name="zen_mode_off" msgid="1736604456618147306">"বন্ধ আছে"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"সেট-আপ করুন"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"সেটিংসে গিয়ে ম্যানেজ করুন"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{কোনও মোড চালু নেই}=1{{mode} চালু আছে}one{# মোড চালু আছে}other{# মোড চালু আছে}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"অ্যালার্ম, রিমাইন্ডার, ইভেন্ট, এবং আপনার নির্দিষ্ট করে দেওয়া ব্যক্তিদের কল ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"অ্যালার্ম ছাড়া অন্য কোনও আওয়াজ বা ভাইব্রেশন হবে না। তবে সঙ্গীত, ভিডিও, এবং গেম সহ আপনি যা কিছু চালাবেন তার আওয়াজ শুনতে পাবেন।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"কাস্টমাইজ করুন"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ধীরে চার্জ হচ্ছে • পুরো চার্জ হতে <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> লাগবে"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"লক স্ক্রিনে উইজেট"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> উইজেট লক স্ক্রিনে যোগ করা হয়েছে"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাস্টমাইজ করুন"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"বাতিল করুন"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"রেকর্ড বা কাস্ট করার সময় স্ক্রিনে বা ডিভাইসে দৃশ্যমান সব তথ্য <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> অ্যাক্সেস করতে পারবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং আপনার চালানো অডিও সম্পর্কিত তথ্য রয়েছে।"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"রেকর্ডিং বা কাস্টিং শুরু করতে চান?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"যে পরিষেবা এই ফাংশন প্রদান করছে, সেটি রেকর্ড বা কাস্ট করার সময় আপনার স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো হয়েছে এমন সব তথ্য অ্যাক্সেস করতে পারবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং আপনার চালানো অডিও সম্পর্কিত তথ্য রয়েছে।"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"পুরো স্ক্রিন"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"একটি অ্যাপ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"অ্যাপ শেয়ার বা রেকর্ড করুন"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ব্যবহার করে রেকর্ডিং বা কাস্টিং শুরু করবেন?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"আপনি শেয়ার, রেকর্ড বা কাস্ট করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সব কিছুই <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"আপনি কোনও অ্যাপ শেয়ার, রেকর্ড বা কাস্ট করার সময়, সেই অ্যাপে দেখা যায় বা চালানো হয় এমন সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"শুরু করুন"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর সাথে আপনার স্ক্রিন শেয়ার করবেন?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"একটি অ্যাপ শেয়ার করুন"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"সম্পূর্ণ স্ক্রিন শেয়ার করুন"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপনার সম্পূর্ণ স্ক্রিন শেয়ার করার সময়, স্ক্রিনে থাকা সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"কোনও অ্যাপ শেয়ার করার সময়, সেই অ্যাপে দেখা ও চালানো হয় এমন সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্রিন শেয়ার করুন"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> এই বিকল্পটি বন্ধ করে দিয়েছে"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"কাস্ট করা শুরু করবেন?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"আপনি কাস্ট করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"আপনি কোনও অ্যাপ কাস্ট করার সময়, ওই অ্যাপে দেখানো বা চালানো হয় এমন সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"কাস্ট করা শুরু করুন"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"আপনার স্ক্রিন কাস্ট করুন?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"একটি অ্যাপ কাস্ট করুন"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"সম্পূর্ণ স্ক্রিন কাস্ট করুন"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"আপনি সম্পূর্ণ স্ক্রিন কাস্ট করলে, আপনার স্ক্রিনে থাকা সব কিছুই দেখা যাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"আপনি কোনও অ্যাপ কাস্ট করলে, ওই অ্যাপে কিছু দেখানো বা চালানো হলে তা দেখা যাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"স্ক্রিন কাস্ট করুন"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"শেয়ার করা শুরু করবেন?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"আপনি শেয়ার, রেকর্ড বা কাস্ট করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সব কিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"আপনি কোনও অ্যাপ শেয়ার, রেকর্ড বা কাস্ট করার সময়, সেই অ্যাপে দেখা যায় বা চালানো হয় এমন সব কিছু Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"শুরু করুন"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"পরবর্তী"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"আপনি অ্যাপ পাল্টানোর সময় শেয়ারিং পজ করা হয়"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"এর পরিবর্তে এই অ্যাপ শেয়ার করুন"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"আবার পাল্টান"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"অ্যাক্সেসিবিলিটি"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"কীবোর্ড শর্টকাট"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"সার্চ শর্টকাট"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"কোনও সার্চ ফলাফল নেই"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"আইকন আড়াল করুন"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"আইকন বড় করুন"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"হোমপেজে যাওয়ার জেসচার"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"অ্যাকশন কী"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হয়ে গেছে"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"অসাধারণ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ফিরে যান"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ফিরে যেতে, টাচপ্যাডে যেকোনও জায়গায় তিনটি আঙুল দিয়ে বাঁদিক বা ডানদিকে সোয়াইপ করুন।\n\nএছাড়া, এটির জন্য আপনি কীবোর্ড শর্টকাট অ্যাকশন + ESC বোতাম প্রেস করতে পারবেন।"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"হোমে যান"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"যেকোনও সময়ে আপনার হোম স্ক্রিনে যেতে, আপনার স্ক্রিনের একদম নিচের থেকে তিনটি আঙুল দিয়ে উপরের দিকে সোয়াইপ করুন।"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"টাচপ্যাডে, তিনটি আঙুল ডান ও বাঁদিকে সরানো দেখানো হচ্ছে"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ডিভাইসের স্ক্রিনে ফিরে যাওয়ার জেসচারের অ্যানিমেশন দেখানো হচ্ছে"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীবোর্ড ব্যাকলাইট"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-এর মধ্যে %1$d লেভেল"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"হোম কন্ট্রোল"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"হোমে যেতে, টাচপ্যাডে তিনটি আঙুল দিয়ে উপরের দিকে সোয়াইপ করুন"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"সম্প্রতি ব্যবহার করা অ্যাপ দেখতে, টাচপ্যাডে তিনটি আঙুল ব্যবহার করে উপরের দিকে সোয়াইপ করে ধরে রাখুন"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপনার সব অ্যাপ দেখতে, কীবোর্ডে অ্যাকশন কী প্রেস করুন"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"রিড্যাক্ট করা হয়েছে"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"দেখার জন্য আনলক করুন"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ফিরে যেতে টাচপ্যাড ব্যবহার করুন"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"তিনটি আঙুলের ব্যবহার করে ডান বা বাঁদিকে সোয়াইপ করুন। আরও জেসচার সম্পর্কে জানতে ট্যাপ করুন।"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"হোমে যেতে টাচপ্যাড ব্যবহার করুন"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"তিনটি আঙুল ব্যবহার করে উপরের দিকে সোয়াইপ করে ধরে রাখুন। আরও জেসচার সম্পর্কে জানতে ট্যাপ করুন।"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"সব অ্যাপ দেখতে আপনার কীবোর্ড ব্যবহার করুন"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"যেকোনও সময় অ্যাকশন কী প্রেস করুন। আরও জেসচার সম্পর্কে জানতে ট্যাপ করুন।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচার এখন ব্রাইটনেস বারের একটি অংশ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"আপনি এখন স্ক্রিনের উপর থেকে ব্রাইটনেস লেভেল কমিয়েও, স্ক্রিন অতিরিক্ত কম ব্রাইটনেস করতে পারবেন।\n\nআপনি অন্ধকারে থাকলে এটি সবথেকে ভালো কাজ করে।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচারের শর্টকাট সরান"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচারের শর্টকাট সরানো হয়েছে। আপনার ব্রাইটনেস কম করতে, নিয়মিত ব্রাইটনেস বার ব্যবহার করুন।"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 2bc13c0fac5e..c274e2e4b8d2 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Pokrenuti snimanje?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Dok snimate, Android ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Dok snimate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Pokreni snimanje"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimanje zvuka"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk na uređaju"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk s vašeg uređaja, npr. muzika, pozivi i melodije zvona"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string> <string name="cancel" msgid="1089011503403416730">"Otkaži"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotip aplikacije"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdi"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Pokušaj ponovo"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da otkažete autentifikaciju"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da uparite novi uređaj"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadane postavke nije uspjelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Zadana postavka"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Automatski titlovi"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatski titlovi"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblokirati mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblokirati kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblokirati kameru i mikrofon uređaja?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Postavite"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte opcijom u postavkama"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih načina rada}=1{Način rada {mode} je aktivan}one{# način rada je aktivan}few{# načina rada su aktivna}other{# načina rada je aktivno}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivalaca koje odredite. I dalje ćete čuti sve što ste odabrali za reprodukciju, uključujući muziku, videozapise i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što izaberete za reprodukciju, uključujući muziku, videozapise i igre."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prilagodi"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sporo punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Vidžeti na zaključanom ekranu"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> je dodan na zaključani ekran"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> će imati pristup svim informacijama koje su vidljive na ekranu ili koje se reproduciraju s uređaja tokom snimanja ili emitiranja. To uključuje informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Pokrenuti snimanje ili emitiranje?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje su vidljive na ekranu ili koje se reproduciraju s uređaja tokom snimanja ili emitiranja. To uključuje informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Cijeli ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikacija"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Dijelite ili snimite aplikaciju"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Pokrenuti snimanje ili emitiranje uz aplikaciju <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada dijelite, snimate ili emitirate, aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kada dijelite, snimate ili emitirate aplikaciju, aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Dijeliti ekran s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeli jednu aplikaciju"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeli cijeli ekran"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli ekran, sve što je na ekranu će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeli ekran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućila tu opciju"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Pokrenuti emitiranje?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada emitirate, Android ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Pokreni emitiranje"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Emitirati ekran?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Emitiraj jednu aplikaciju"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Emitiraj cijeli ekran"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kada emitirate cijeli ekran, vidljivo je sve što je na ekranu. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kada emitirate aplikaciju, vidljivo je sve što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Emitiraj ekran"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Pokrenuti dijeljenje?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kada dijelite, snimate ili emitirate, Android ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kada dijelite, snimate ili emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Pokreni"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Naprijed"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Dijeljenje se pauzira kada promijenite aplikaciju"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Umjesto toga, dijeli aplikaciju"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Vrati se"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pristupačnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Prečice tastature"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Prečica pretraživanja"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nema rezultata pretraživanja"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sužavanja"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona proširivanja"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za povratak na početni ekran"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka radnji"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se pomjeraju desno-lijevo"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran uređaja pokazuje animaciju pokreta unazad"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da se vratite, prevucite ulijevo ili udesno s tri prsta bilo gdje na dodirnoj podlozi.\n\nZa ovo možete koristiti i radnju za prečicu i Esc na tastaturi."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Sjajno!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvršili ste pokret za povratak."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Odlazak na početni ekran"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da odete na početni ekran bilo kada, prevucite s dna ekrana nagore s tri prsta."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Odlično!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Izvršili ste pokret za otvaranje početnog zaslona."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka za radnju"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Da biste pristupili svojim aplikacijama, pritisnite tipku za radnje na tipkovnici."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Izvršili ste pokret tipke za radnju.\n\nRadnja + / prikazuje sve prečace koji su vam dostupni."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tastature"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da se vratite na početnu stranicu, prevucite nagore s tri prsta na dodirnoj podlozi"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Da pregledate nedavne aplikacije, prevucite nagore i zadržite s tri prsta na dodirnoj podlozi"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da pregledate sve aplikacije, pritisnite tipku radnji na tastaturi"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redigovano"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte da pregledate"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Koristite dodirnu podlogu da se vratite"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Prevucite ulijevo ili udesno s tri prsta. Dodirnite da saznate za više pokreta."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Koristite dodirnu podlogu da se vratite na početnu stranicu"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite s tri prsta. Dodirnite da saznate za više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da pregledate sve aplikacije"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku radnji bilo kada. Dodirnite da saznate za više pokreta."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjenje je sada dio trake za osvijetljenost"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sada možete dodatno zatamniti ekran daljnjim smanjenjem nivoa osvijetljenosti s vrha ekrana.\n\nOvo najbolje funkcionira u tamnom okruženju."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečicu za dodatno zatamnjenje"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Prečica za dodatno zatamnjenje je uklonjena. Da smanjite osvijetljenost, koristite običnu traku za osvijetljenost."</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index a9ab9fc7789c..a1cea49ac2e0 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Gravació de pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Vols iniciar una gravació?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Mentre graves, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Mentre graves una aplicació, Android té accés a qualsevol cosa que es mostri o que es reprodueixi en aquella aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Inicia una gravació"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grava l\'àudio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Àudio del dispositiu"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"So del dispositiu, com ara música, trucades i sons de trucada"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envia"</string> <string name="cancel" msgid="1089011503403416730">"Cancel·la"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotip de l\'aplicació"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirma"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Torna-ho a provar"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca per cancel·lar l\'autenticació"</string> @@ -296,7 +304,7 @@ <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca per connectar o desconnectar un dispositiu"</string> <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Vincula un dispositiu nou"</string> <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Mostra-ho tot"</string> - <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza\'l"</string> + <string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza el Bluetooth"</string> <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connectat"</string> <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartició d\'àudio"</string> <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Desat"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fes clic per vincular un dispositiu nou"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"No s\'ha pogut actualitzar el valor predefinit"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Valors predefinits"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtítols instantanis"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítols instantanis"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vols desbloquejar el micròfon del dispositiu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vols desbloquejar la càmera del dispositiu?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vols desbloquejar la càmera i el micròfon del dispositiu?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuració"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivat"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configura"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestiona a la configuració"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hi ha cap mode actiu}=1{{mode} està actiu}many{Hi ha # de modes actius}other{Hi ha # modes actius}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes, recordatoris, esdeveniments i trucades de les persones que especifiquis. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalitza"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregant lentament • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets a la pantalla de bloqueig"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"El widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> s\'ha afegit a la pantalla de bloqueig"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalitza"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignora"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tindrà accés a tota la informació que es veu en pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara contrasenyes, detalls dels pagaments, fotos, missatges i àudio que reprodueixis."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vols començar a gravar o emetre contingut?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servei que ofereix aquesta funció tindrà accés a tota la informació visible a la teva pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara les contrasenyes, les dades de pagament, les fotos, els missatges i àudio que reprodueixis."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tota la pantalla"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Una sola aplicació"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Comparteix o grava una aplicació"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vols començar a gravar o emetre contingut amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quan comparteixes, graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quan comparteixes, graves o emets una aplicació, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es mostri o que es reprodueixi en aquella aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Inicia"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vols compartir la pantalla amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Comparteix una aplicació"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Comparteix tota la pantalla"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quan comparteixes tota la pantalla, qualsevol cosa que es mostra en pantalla és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quan comparteixes una aplicació, qualsevol cosa que es mostra o que es reprodueix en aquesta aplicació és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Comparteix la pantalla"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha desactivat aquesta opció"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vols iniciar una emissió?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quan emets contingut, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quan emets una aplicació, Android té accés a qualsevol cosa que es mostri o que es reprodueixi en aquella aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Inicia una emissió"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Vols emetre la pantalla?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Emet una aplicació"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Emet tota la pantalla"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Quan emets tota la pantalla, qualsevol cosa que es mostra en pantalla és visible. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Quan emets una aplicació, qualsevol cosa que es mostra o que es reprodueix en aquesta aplicació és visible. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Emet la pantalla"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Vols començar a compartir?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Quan comparteixes, graves o emets contingut, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Quan comparteixes, graves o emets una aplicació, Android té accés a qualsevol cosa que es mostri o que es reprodueixi en aquella aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Inicia"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Següent"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"La compartició es posa en pausa quan canvies d\'aplicació"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Comparteix aquesta aplicació"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Torna a canviar"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibilitat"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tecles de drecera"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Dreceres de cerca"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No hi ha cap resultat de la cerca"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Replega la icona"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Desplega la icona"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest Inici"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla d\'acció"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fet"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ben fet!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Torna"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Per tornar enrere, llisca cap a l\'esquerra o cap a la dreta amb tres dits en qualsevol lloc del ratolí tàctil.\n\nTambé pots utilitzar les tecles d\'accions de drecera+Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ves a la pantalla d\'inici"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Per anar a la pantalla d\'inici en qualsevol moment, fes lliscar tres dits cap amunt des de la part inferior de la pantalla."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Ratolí tàctil que mostra tres dits que es mouen cap a la dreta i cap a l\'esquerra"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositiu que mostra l\'animació del gest per anar enrere"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivell %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controls de la llar"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Per anar a la pantalla d\'inici, llisca tres dits cap amunt al ratolí tàctil"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per veure les aplicacions recents, llisca cap amunt amb tres dits i mantén premut al ratolí tàctil"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per veure totes les aplicacions, prem la tecla d\'acció al teclat"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Emmascarat"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloqueja per veure"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilitza el ratolí tàctil per tornar enrere"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Fes lliscar tres dits cap a l\'esquerra o cap a la dreta. Toca per aprendre més gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilitza el ratolí tàctil per anar a la pantalla d\'inici"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Llisca cap amunt amb tres dits i mantén premut. Toca per aprendre més gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilitza el teclat per veure totes les aplicacions"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prem la tecla d\'acció en qualsevol moment. Toca per aprendre més gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Atenuació extra ara forma part de la barra de brillantor"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ara pots atenuar encara més la pantalla abaixant-ne el nivell de brillantor des de la part superior.\n\nFunciona millor si et trobes en un lloc fosc."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Suprimeix la drecera d\'atenuació extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"S\'ha suprimit la drecera d\'atenuació extra. Per abaixar la brillantor, utilitza la barra de brillantor normal."</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 194057a7309c..d1bffd29d42e 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Nahrávání obrazovky"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Začít nahrávat?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Během nahrávání má Android přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Dejte proto pozor na hesla, platební údaje, zprávy, fotografie, zvukové záznamy nebo videa."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Během nahrávání aplikace má Android přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s informacemi, jako jsou hesla, platební údaje, zprávy, fotky, zvukové záznamy nebo videa."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Začít nahrávat"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrávat zvuk"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk zařízení"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk ze zařízení, například hudba, hovory a vyzvánění"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Odeslat"</string> <string name="cancel" msgid="1089011503403416730">"Zrušit"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo aplikace"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdit"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Zkusit znovu"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Klepnutím zrušíte ověření"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zařízení"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Předvolbu nelze aktualizovat"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Předvolba"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Okamžité titulky"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Okamžité titulky"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokovat mikrofon zařízení?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokovat fotoaparát zařízení?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokovat fotoaparát a mikrofon zařízení?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavení"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuto"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastavit"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Spravovat v nastavení"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žádné aktivní režimy}=1{Režim {mode} je aktivní}few{# režimy jsou aktivní}many{# režimu je aktivních}other{# režimů je aktivních}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků, upozornění, událostí a volajících, které zadáte. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudou vás rušit zvuky ani vibrace s výjimkou budíků. Nadále uslyšíte veškerý obsah, který si sami pustíte (např. hudba, videa nebo hry)."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Přizpůsobit"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Pomalé nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgety na obrazovce uzamčení"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Na obrazovku uzamčení byl přidán widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Přizpůsobit"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavřít"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bude mít přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze za řízení při nahrávání nebo odesílání. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Začít nahrávat nebo odesílat?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba, která tuto funkci poskytuje, bude mít při nahrávání nebo odesílání přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze zařízení. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Celá obrazovka"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikace"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Sdílení nebo nahrání aplikace"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Začít nahrávat nebo odesílat pomocí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Během sdílení, nahrávání nebo odesílání má <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Během sdílení, nahrávání nebo odesílání aplikace má <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začít"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Sdílet obrazovku s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Sdílet jednu aplikaci"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Sdílet celou obrazovku"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Při sdílení celé obrazovky vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se na obrazovce nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Při sdílení aplikace vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se ve sdílené aplikaci nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Sdílet obrazovku"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> tuto možnost zakázala"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Začít odesílat?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Během odesílání má Android přístup ke všemu, co je viditelné na obrazovce nebo se přehrává v zařízení. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Během odesílání aplikace má Android přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s informacemi, jako jsou hesla, platební údaje, zprávy, fotky, zvukové záznamy a videa."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Začít odesílat"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Odeslat obrazovku?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Odeslat jednu aplikaci"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Odeslat celou obrazovku"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Při odesílání celé obrazovky je vidět vše, co se na obrazovce nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Při odesílání aplikace je vidět vše, co se v aplikaci nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Odesílání obrazovky"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Začít sdílet?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Během sdílení, nahrávání nebo odesílání má Android přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Během sdílení, nahrávání nebo odesílání aplikace má Android přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s informacemi, jako jsou hesla, platební údaje, zprávy, fotky, zvukové záznamy a videa."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Začít"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Další"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Když přepnete aplikace, sdílení se pozastaví"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Sdílet aplikaci"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Přepnout zpět"</string> @@ -565,8 +577,8 @@ <string name="media_projection_action_text" msgid="3634906766918186440">"Spustit"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Žádná oznámení"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Žádná nová oznámení"</string> - <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Je zapnuté zeslabení oznámení"</string> - <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Když dostanete příliš mnoho oznámení najednou, až na dvě minuty se sníží hlasitost zařízení a oznámení se omezí."</string> + <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Oznámení jsou zeslabená"</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Když máte moc oznámení najednou, až na dvě minuty se sníží hlasitost zařízení a oznámení se omezí."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Vypnout"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Starší oznámení se zobrazí po odemknutí"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zařízení spravuje rodič"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Přístupnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klávesové zkratky"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Vyhledat zkratky"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Žádné výsledky hledání"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sbalení"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalení"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"nebo"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto domů"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akční klávesa"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Výborně!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zpět"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pokud se chcete vrátit zpět, stačí kdekoli na touchpadu přejet třemi prsty doleva nebo doprava.\n\nMůžete také použít klávesovou zkratku Akce + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Přejít na plochu"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Na plochu přejdete kdykoli přejetím třemi prsty ze spodní části obrazovky nahoru."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad se třemi prsty, které se pohybují doprava a doleva"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zařízení s animaci gesta k vrácení zpět"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvícení klávesnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Úroveň %1$d z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládání domácnosti"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pokud se chcete vrátit domů, přejeďte po touchpadu třemi prsty nahoru"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pokud chcete zobrazit poslední aplikace, přejeďte na touchpadu třemi prsty nahoru a podržte je"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pokud chcete zobrazit všechny aplikace, stiskněte na klávesnici akční klávesu"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Odstraněno"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"K zobrazení je potřeba zařízení odemknout"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Návrat zpět pomocí touchpadu"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Přejeďte třemi prsty doleva nebo doprava. Další gesta zjistíte klepnutím."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Návrat domů pomocí touchpadu"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Přejeďte třemi prsty nahoru a podržte je. Další gesta zjistíte klepnutím."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazení všech aplikací pomocí klávesnice"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kdykoli stiskněte akční klávesu. Další gesta zjistíte klepnutím."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Na sloupci jasu lze nově nastavit velmi tmavou obrazovku"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Obrazovku můžete v horní části nastavit jako velmi tmavou tím, že ještě víc snížíte jas.\n\nNejlépe to funguje ve tmavém prostředí."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstranit zkratku pro velmi tmavou obrazovku"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Zkratka pro velmi tmavou obrazovku byla odstraněna. Jas můžete snížit pomocí standardního sloupce jasu."</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index ba1babf21ebe..70ff22c8903c 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Skærmoptagelse"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Vil du starte optagelsen?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Mens du optager, har Android adgang til alt, der er synligt på din skærm, eller som afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Mens du optager en app, har Android adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start optagelse"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Optag lyd"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Enhedslyd"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Lyd fra din enhed såsom musik, opkald og ringetoner"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Annuller"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Applogo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekræft"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Prøv igen"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tryk for at annullere godkendelsen"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik for at parre en ny enhed"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Forindstillingen kunne ikke opdateres"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forindstilling"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Livetekstning"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Livetekstning"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du fjerne blokeringen af enhedens mikrofon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du fjerne blokeringen af enhedens kamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du fjerne blokeringen af enhedens kamera og mikrofon?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Indstillinger"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Til"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Fra"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfigurer"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrer i indstillingerne"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ingen aktive tilstande}=1{{mode} er aktiv}one{# tilstand er aktiv}other{# tilstande er aktive}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer, påmindelser, begivenheder og opkald fra udvalgte personer, du selv angiver. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du bliver ikke forstyrret af lyde eller vibrationer, undtagen fra alarmer. Du kan stadig høre alt, du vælger at afspille, f.eks. musik, videoer og spil."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Tilpas"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader langsomt • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets på låseskærmen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g> er føjet til låseskærmen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpas"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Luk"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vil du begynde at optage eller caste?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten, der tilbyder denne funktion, får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Hele skærmen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Én app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Del eller optag en app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vil du begynde at optage eller caste via <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Når du deler, optager eller caster, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der er synligt på din skærm eller afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Når du deler, optager eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele din skærm med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skærmen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skærmen, er alt på din skærm synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt, der vises eller afspilles i den pågældende app, synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skærm"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har deaktiveret denne valgmulighed"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vil du begynde at caste?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Når du caster, har Android adgang til alt, der vises på din skærm eller afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Når du caster en app, har Android adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Vil du caste din skærm?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast én app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast hele skærmen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Når du caster hele din skærm, er alt på skærmen synligt. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Når du caster en app, er alt, der vises eller afspilles i appen, synligt. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast skærm"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Vil du begynde at dele?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Når du deler, optager eller caster, har Android adgang til alt, der er synligt på din skærm eller afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Når du deler, optager eller caster en app, har Android adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Næste"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Delingen sættes på pause, når du skifter apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Del denne app i stedet"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Skift tilbage"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Hjælpefunktioner"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tastaturgenveje"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Genveje til søgning"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Der er ingen søgeresultater"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon for Skjul"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon for Udvid"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bevægelse for at gå til startskærm"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Udfør"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sådan!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbage"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Du kan gå tilbage ved at stryge mod venstre eller højre med tre fingre et vilkårligt sted på touchpladen.\n\nDu kan også bruge tastaturgenvejen Alt + Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startskærmen"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Du kan til enhver tid stryge opad med tre fingre fra bunden af skærmen, hvis du vil gå til startskærmen."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchplade viser tre fingre, der bevæger sig til højre og venstre"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhedsskærm, der viser en animation, som demonstrerer, hvordan man går tilbage"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturets baggrundslys"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d af %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemmestyring"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Du kan gå til startskærmen ved at stryge opad med tre fingre på touchpladen"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Du kan se nyligt brugte apps ved at stryge opad og holde tre fingre nede på touchpladen"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Du kan se alle dine apps ved at trykke på handlingstasten på dit tastatur"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Skjult"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås op for at se"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Brug din touchplade til at gå tilbage"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Stryg til venstre eller højre med tre fingre. Tryk for at lære flere bevægelser."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Brug din touchplade til at gå til startskærmen"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Stryg opad, og hold tre fingre nede. Tryk for at lære flere bevægelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Brug dit tastatur til at se alle apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryk på handlingstasten når som helst. Tryk for at lære flere bevægelser."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra dæmpet belysning er nu en del af lysstyrkebjælken"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Du kan nu dæmpe skærmens belysning ekstra meget ved at reducere lysstyrken endnu mere fra toppen af skærmen.\n\nDette fungerer bedst i mørke omgivelser."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjern genvejen til ekstra dæmpet belysning"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Genvejen til ekstra dæmpet belysning er fjernet. Brug den almindelige lysstyrkebjælke til at reducere lysstyrken."</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 62ede78ff214..0bcf097ab4f9 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Bildschirmaufzeichnung"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Aufnahme starten?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Während der Aufnahme hat Android Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Während der Aufnahme einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Aufnahme starten"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio aufnehmen"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio des Geräts"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Audioinhalte auf deinem Gerät, wie Musik, Anrufe und Klingeltöne"</string> @@ -128,24 +138,24 @@ <string name="screenrecord_start_error" msgid="2200660692479682368">"Fehler beim Start der Bildschirmaufzeichnung"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Aufzeichnung beenden?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Du zeichnest momentan deinen gesamten Bildschirm auf"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du zeichnest momentan Inhalte der <xliff:g id="APP_NAME">%1$s</xliff:g> auf"</string> - <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Aufnahme beenden"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Du zeichnest momentan Inhalte der App <xliff:g id="APP_NAME">%1$s</xliff:g> auf"</string> + <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Aufzeichnung beenden"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Bildschirm wird geteilt"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Bildschirmfreigabe beenden?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du teilst momentan deinen gesamten Bildschirm mit der <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Du teilst momentan deinen gesamten Bildschirm mit der App <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Du teilst momentan deinen gesamten Bildschirm mit einer App"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du teilst momentan Inhalte der <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Du teilst momentan die App <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Du teilst momentan Inhalte einer App"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Freigabe beenden"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Bildschirm wird übertragen"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Übertragung abbrechen?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du überträgst momentan deinen gesamten Bildschirm auf das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du überträgst momentan deinen gesamten Bildschirm auf ein Gerät in der Nähe"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du überträgst momentan Inhalte der <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> auf das Gerät „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du überträgst momentan Inhalte der <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> auf ein Gerät in der Nähe"</string> - <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du überträgst momentan Inhalte auf das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> - <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du überträgst momentan Inhalte auf ein Gerät in der Nähe"</string> - <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Streaming beenden"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Streaming beenden?"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Du streamst momentan deinen gesamten Bildschirm auf das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Du streamst momentan deinen gesamten Bildschirm auf ein Gerät in der Nähe"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Du streamst momentan die App <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> auf das Gerät „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Du streamst momentan Inhalte der App <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> auf ein Gerät in der Nähe"</string> + <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Du streamst momentan Inhalte auf das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string> + <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Du streamst momentan auf ein Gerät in der Nähe"</string> + <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Streamen beenden"</string> <string name="close_dialog_button" msgid="4749497706540104133">"Schließen"</string> <string name="issuerecord_title" msgid="286627115110121849">"Problem aufzeichnen"</string> <string name="issuerecord_background_processing_label" msgid="1666840264959336876">"Aufzeichnung wird verarbeitet"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Senden"</string> <string name="cancel" msgid="1089011503403416730">"Abbrechen"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App-Logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bestätigen"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Noch einmal versuchen"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Zum Abbrechen der Authentifizierung tippen"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicken, um neues Gerät zu koppeln"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Voreinstellung konnte nicht aktualisiert werden"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voreinstellung"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Automatische Untertitel"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatische Untertitel"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Blockierung des Gerätemikrofons aufheben?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Blockierung der Gerätekamera aufheben?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blockierung von Gerätekamera und Gerätemikrofon aufheben?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Einstellungen"</string> <string name="zen_mode_on" msgid="9085304934016242591">"An"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Aus"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Einrichten"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"In den Einstellungen verwalten"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Keine aktiven Modi}=1{{mode} aktiv}other{# aktiv}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe, Erinnerungen, Termine sowie Anrufe von zuvor von dir festgelegten Personen. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Klingeltöne und die Vibration werden deaktiviert, außer für Weckrufe. Du hörst jedoch weiterhin Sound, wenn du dir Musik anhörst, Videos ansiehst oder Spiele spielst."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Anpassen"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird langsam geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets auf dem Sperrbildschirm"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ zum Sperrbildschirm hinzugefügt"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassen"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Schließen"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Die <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Aufnahme oder Stream starten?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Der Anbieter dieser App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Gesamter Bildschirm"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Einzelne App"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"App teilen oder aufnehmen"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Aufnehmen oder Streamen mit der <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> App starten?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Beim Teilen, Aufnehmen oder Streamen hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Beim Teilen, Aufnehmen oder Streamen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Starten"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bildschirm mit <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> teilen?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eine App streamen"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Gesamten Bildschirm teilen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wenn du den gesamten Bildschirm teilst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles auf dem Bildschirm sichtbar. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wenn du eine App streamst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles sichtbar, was in dieser App angezeigt oder abgespielt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bildschirm teilen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> hat diese Option deaktiviert"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Stream starten?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Beim Streamen hat Android Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Beim Streamen einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Stream starten"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Bildschirm streamen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Eine App streamen"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Gesamten Bildschirm streamen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Wenn du den gesamten Bildschirm streamst, ist alles auf dem Bildschirm sichtbar. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Wenn du eine App streamst, ist alles sichtbar, was in dieser App angezeigt oder abgespielt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Bildschirm streamen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Teilen starten?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Beim Teilen, Aufnehmen oder Streamen hat Android Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Beim Teilen, Aufnehmen oder Streamen einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Starten"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Weiter"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Das Teilen wird pausiert, wenn du zwischen Apps wechselst"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Stattdessen diese App teilen"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Zurückwechseln"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Bedienungshilfen"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tastenkürzel"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Tastenkürzel suchen"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Keine Suchergebnisse"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Symbol „Minimieren“"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Symbol „Maximieren“"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oder"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Touch-Geste „Startbildschirm“"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aktionstaste"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fertig"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Gut gemacht!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zurück"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Wenn du zurückgehen möchtest, wische an einer beliebigen Stelle des Touchpads mit drei Fingern nach links oder rechts.\n\nDu kannst stattdessen auch die Tastenkombination „Aktion“ + „ESC“ verwenden."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Startbildschirm"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Du kannst jederzeit zum Startbildschirm gehen, indem du mit drei Fingern vom unteren Displayrand nach oben wischst."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mit drei Fingern, die sich nach links und rechts bewegen"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Bildschirm zeigt eine Animation der Touch-Geste „Zurück“"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturbeleuchtung"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d von %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Smart-Home-Steuerung"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Wenn du den Startbildschirm aufrufen möchtest, wische auf dem Touchpad mit drei Fingern nach oben"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Um zuletzt verwendete Apps aufzurufen, wische mit 3 Fingern nach oben und halte das Touchpad gedrückt"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Wenn du alle deine Apps aufrufen möchtest, drücke auf der Tastatur die Aktionstaste"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Entfernt"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Zum Ansehen entsperren"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Über das Touchpad zurückgehen"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Wische mit drei Fingern nach links oder rechts. Tippe für mehr Infos zu Touch-Gesten."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Über das Touchpad zum Startbildschirm zurückkehren"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Wische mit 3 Fingern nach oben und halte das Touchpad gedrückt. Tippe für mehr Infos zu Touch-Gesten."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Über die Tastatur alle Apps aufrufen"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Du kannst jederzeit die Aktionstaste drücken. Tippe für mehr Infos zu Touch-Gesten."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"„Extradunkel“ jetzt auf Helligkeitsleiste verfügbar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Du kannst das Display jetzt extradunkel machen, indem du die Helligkeit vom oberen Displayrand aus noch weiter senkst.\n\nDas funktioniert in dunklen Umgebungen am besten."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Verknüpfung für „Extradunkel“ entfernen"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Verknüpfung für „Extradunkel“ wurde entfernt. Wenn du die Helligkeit reduzieren möchtest, verwende einfach die normale Helligkeitsleiste."</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 5025f6d91513..4db7b6c34471 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Εγγραφή οθόνης"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Έναρξη εγγραφής;"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Όταν κάνετε εγγραφή, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Όταν κάνετε εγγραφή μιας εφαρμογής, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Έναρξη εγγραφής"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Ηχογράφηση"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Ήχος συσκευής"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Ήχος από τη συσκευή σας, όπως μουσική, κλήσεις και ήχοι κλήσης"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Αποστολή"</string> <string name="cancel" msgid="1089011503403416730">"Ακύρωση"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Λογότυπο εφαρμογής"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Επιβεβαίωση"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Δοκιμάστε ξανά"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Πατήστε για ακύρωση του ελέγχου ταυτότητας"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Κάντε κλικ για σύζευξη νέας συσκευής"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Δεν ήταν δυνατή η ενημέρωση της προεπιλογής"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Προεπιλογή"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Ζωντανοί υπότιτλοι"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Ζωντανοί υπότιτλοι"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Κατάργηση αποκλεισμού μικροφώνου συσκευής;"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Κατάργηση αποκλεισμού κάμερας συσκευής;"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Κατάργηση αποκλεισμού κάμερας και μικροφώνου συσκευής;"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ρυθμίσεις"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Ανενεργό"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Ρύθμιση"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Διαχείριση στις ρυθμίσεις"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Δεν υπάρχει ενεργή λειτουργία}=1{{mode} ενεργή λειτουργία}other{# ενεργές λειτουργίες}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια, υπενθυμίσεις, συμβάντα και καλούντες που έχετε καθορίσει. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Δεν θα ενοχλείστε από ήχους και δονήσεις, παρά μόνο από ξυπνητήρια. Θα εξακολουθείτε να ακούτε όλο το περιεχόμενο που επιλέγετε να αναπαραγάγετε, συμπεριλαμβανομένης της μουσικής, των βίντεο και των παιχνιδιών."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Προσαρμογή"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Αργή φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Γραφικά στοιχεία στην οθόνη κλειδώματος"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Το γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g> προστέθηκε στην οθόνη κλειδώματος"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Προσαρμογή"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Παράβλεψη"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Έναρξη εγγραφής ή μετάδοσης;"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Η υπηρεσία που παρέχει αυτήν τη λειτουργία θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Ολόκληρη την οθόνη"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Μία εφαρμογή"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Κοινή χρήση ή εγγραφή εφαρμογής"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Έναρξη εγγραφής ή μετάδοσης με <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>;"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση μιας εφαρμογής, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Έναρξη"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Κοινή χρήση της οθόνης με την εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>;"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Κοινή χρήση μίας εφαρμογής"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Κοινή χρήση ολόκληρης της οθόνης"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Όταν μοιράζεστε ολόκληρη την οθόνη, οτιδήποτε εμφανίζεται στην οθόνη σας είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Όταν μοιράζεστε μια εφαρμογή, οτιδήποτε εμφανίζεται ή αναπαράγεται σε αυτή την εφαρμογή, είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Κοινή χρήση οθόνης"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> απενεργοποίησε αυτή την επιλογή"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Έναρξη μετάδοσης;"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Όταν κάνετε μετάδοση, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Όταν κάνετε μετάδοση μιας εφαρμογής, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Έναρξη μετάδοσης"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Να γίνει μετάδοση της οθόνης σας;"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Μετάδοση μίας εφαρμογής"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Μετάδοση ολόκληρης της οθόνης"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Όταν κάνετε μετάδοση ολόκληρης της οθόνης, όλο το περιεχόμενο της οθόνης είναι ορατό. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Όταν κάνετε μετάδοση μιας εφαρμογής, όλο το περιεχόμενο που εμφανίζεται ή αναπαράγεται στην εφαρμογή είναι ορατό. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Μετάδοση οθόνης"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Έναρξη κοινοποίησης περιεχομένου;"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση μιας εφαρμογής, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Έναρξη"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Επόμενο"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Η κοινοποίηση τίθεται σε παύση κατά την εναλλαγή μεταξύ εφαρμογών"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Εναλλακτικά, κοινοποιήστε την εφαρμογή"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Επιστροφή"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Προσβασιμότητα"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Συντομεύσεις πληκτρολογίου"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Συντομεύσεις αναζήτησης"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Κανένα αποτέλεσμα αναζήτησης"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Εικονίδιο σύμπτυξης"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Εικονίδιο ανάπτυξης"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ή"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Κίνηση μετάβασης στην αρχική οθόνη"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Πλήκτρο ενέργειας"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Τέλος"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Μπράβο!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Επιστροφή"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Για να επιστρέψετε, σύρετε προς τα αριστερά ή προς τα δεξιά χρησιμοποιώντας τρία δάχτυλα σε οποιοδήποτε σημείο της επιφάνειας αφής.\n\nΜπορείτε επίσης να χρησιμοποιήσετε τη συντόμευση πληκτρολογίου Action + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Αρχική"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Για μετάβαση στην αρχική οθόνη ανά πάσα στιγμή, σύρετε προς τα επάνω με τρία δάχτυλα από το κάτω μέρος της οθόνης."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Επιφάνεια αφής στην οποία εμφανίζονται τρία δάχτυλα να κινούνται δεξιά και αριστερά"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Οθόνη συσκευής που εμφανίζει μια κινούμενη εικόνα σχετικά με την κίνηση επιστροφής"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Οπίσθιος φωτισμός πληκτρολογίου"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Επίπεδο %1$d από %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Οικιακοί έλεγχοι"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Για μετάβαση στην αρχική οθόνη, σύρετε προς τα επάνω στην επιφάνεια αφής με τρία δάχτυλα"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Για πρόσφατες εφαρμογές, σαρώστε προς τα πάνω με τρία δάχτυλα και κρατήστε τα στην επιφάνεια αφής"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Για να δείτε όλες τις εφαρμογές, πιέστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Αποκρύφτηκε"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ξεκλείδωμα για προβολή"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Χρήση της επιφάνειας αφής για επιστροφή"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα. Πατήστε για να μάθετε περισσότερες κινήσεις."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Χρήση της επιφάνειας αφής για μετάβαση στην αρχική οθόνη"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Σύρετε προς τα πάνω με τρία δάχτυλα και μην τα σηκώσετε. Πατήστε για να δείτε περισσότερες κινήσεις."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Χρήση του πληκτρολογίου για προβολή όλων των εφαρμογών"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Πιέστε το πλήκτρο ενέργειας ανά πάσα στιγμή. Πατήστε για να μάθετε περισσότερες κινήσεις."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Η επιπλέον μείωση φωτεινότητας είναι τώρα μέρος της γραμμής φωτεινότητας"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Τώρα μπορείτε να μειώσετε επιπλέον τη φωτεινότητα της οθόνης, χαμηλώνοντας το επίπεδο φωτεινότητας ακόμα περισσότερο από το επάνω μέρος της οθόνης.\n\nΑυτό λειτουργεί καλύτερα όταν βρίσκεστε σε σκοτεινό περιβάλλον."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Κατάργηση συντόμευσης επιπλέον μείωσης φωτεινότητας"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Η συντόμευση της επιπλέον μείωσης φωτεινότητας καταργήθηκε. Για να χαμηλώσετε τη φωτεινότητα, χρησιμοποιήστε την κανονική γραμμή φωτεινότητας."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index f2ba7040713b..ad2a5b31c29d 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Start recording?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start recording"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls and ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Cancel"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customise"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Start recording or casting?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Entire screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"A single app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Share or record an app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. Be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Cast your screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast one app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast entire screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"When you\'re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"When you\'re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Start sharing?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"When you’re sharing, recording or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"When you’re sharing, recording or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Next"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Sharing pauses when you switch apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Share this app instead"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Switch back"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Keyboard shortcuts"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Search shortcuts"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No search results"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut Action + Esc for this."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 5680cb7ccd04..e31149b85e1e 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Screen Recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Start Recording?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start recording"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls, and ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Cancel"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -527,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Start recording or casting?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Entire screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"A single app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Share or record an app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording, or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording, or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you’re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you’re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Cast your screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast one app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast entire screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"When you’re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"When you’re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Start sharing?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"When you’re sharing, recording, or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"When you’re sharing, recording, or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Next"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Sharing pauses when you switch apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Share this app instead"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Switch back"</string> @@ -1372,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Keyboard shortcuts"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Search shortcuts"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No search results"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string> @@ -1379,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut Action + ESC for this."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great job!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts you have available."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home Controls"</string> @@ -1396,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> @@ -1404,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index f2ba7040713b..ad2a5b31c29d 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Start recording?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start recording"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls and ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Cancel"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customise"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Start recording or casting?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Entire screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"A single app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Share or record an app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. Be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Cast your screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast one app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast entire screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"When you\'re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"When you\'re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Start sharing?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"When you’re sharing, recording or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"When you’re sharing, recording or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Next"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Sharing pauses when you switch apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Share this app instead"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Switch back"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Keyboard shortcuts"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Search shortcuts"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No search results"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut Action + Esc for this."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index f2ba7040713b..ad2a5b31c29d 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Start recording?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start recording"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls and ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Cancel"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string> <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Manage in settings"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No active modes}=1{{mode} is active}other{# modes are active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers you specify. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"You won\'t be disturbed by sounds and vibrations, except from alarms. You\'ll still hear anything you choose to play including music, videos and games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Customise"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets on lock screen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to lock screen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Start recording or casting?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Entire screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"A single app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Share or record an app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. Be careful with things like passwords, payment details, messages, photos, audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Cast your screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast one app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast entire screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"When you\'re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"When you\'re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Start sharing?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"When you’re sharing, recording or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"When you’re sharing, recording or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Next"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Sharing pauses when you switch apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Share this app instead"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Switch back"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Keyboard shortcuts"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Search shortcuts"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No search results"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great work!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut Action + Esc for this."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing 3 fingers moving right and left"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index f99ab9e919f7..f9081482ea8d 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Screen Recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Start Recording?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Start recording"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Record audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Device audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sound from your device, like music, calls, and ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Cancel"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirm"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Try again"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tap to cancel authentication"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Click to pair new device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Unblock device microphone?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Unblock device camera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Unblock device camera and microphone?"</string> @@ -527,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Start recording or casting?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Entire screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"A single app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Share or record an app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Start recording or casting with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording, or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording, or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you’re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you’re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Start casting"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Cast your screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast one app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast entire screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"When you’re casting your entire screen, anything on your screen is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"When you’re casting an app, anything shown or played in that app is visible. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Start sharing?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"When you’re sharing, recording, or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"When you’re sharing, recording, or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Start"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Next"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Sharing pauses when you switch apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Share this app instead"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Switch back"</string> @@ -1372,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Keyboard shortcuts"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Search shortcuts"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No search results"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string> @@ -1379,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Great job!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad showing three fingers moving right and left"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Device screen showing animation for back gesture"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"To go back, swipe left or right using three fingers anywhere on the touchpad.\n\nYou can also use the keyboard shortcut Action + ESC for this."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great job!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts you have available."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home Controls"</string> @@ -1396,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"To go home, swipe up with three fingers on the touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"To view recent apps, swipe up and hold with three fingers on the touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use your touchpad to go back"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe left or right using three fingers. Tap to learn more gestures."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use your touchpad to go home"</string> @@ -1404,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 31344fa7389a..34bcd8f90002 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Grabadora de pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"¿Quieres comenzar a grabar?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Cuando grabes contenido, Android podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Cuando grabes una app, Android podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Iniciar grabación"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabar audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sonidos del dispositivo, como música, llamadas y tonos"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotipo de la app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Volver a intentarlo"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Presiona para cancelar la autenticación"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para vincular un dispositivo nuevo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se pudo actualizar el ajuste predeterminado"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Ajuste predeterminado"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtitulado instantáneo"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitulado instantáneo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Quieres desbloquear el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Quieres desbloquear la cámara del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Quieres desbloquear la cámara y el micrófono del dispositivo?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrar en configuración"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hay modos activos}=1{{mode} está activo}many{# de modos están activos}other{# modos están activos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas de los emisores que especifiques. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Podrás escuchar el contenido que reproduzcas, como música, videos y juegos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lento • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Se agregó el widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a la pantalla de bloqueo"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Descartar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en el dispositivo durante una grabación o transmisión. Se incluyen contraseñas, detalles de pagos, fotos, mensajes y el audio que reproduzcas."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"¿Quieres comenzar a grabar o transmitir contenido?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que brinda esta función tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en el dispositivo durante una grabación o transmisión. Se incluyen contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Pantalla completa"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Una sola app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Comparte o graba una app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"¿Quieres iniciar una grabación o transmisión con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cuando compartas, grabes o transmitas contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cuando compartas, grabes o transmitas una app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Quieres compartir pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir pantalla completa"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes la pantalla completa, todo lo que se muestre es visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una app, todo lo que se muestre o reproduzca en ella será visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> inhabilitó esta opción"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Empezar a transmitir contenido?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cuando transmitas contenido, Android podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cuando transmitas una app, Android podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Empezar"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"¿Quieres transmitir la pantalla?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmitir una app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmitir pantalla entera"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Cuando transmitas la pantalla entera, todo lo que se muestre es visible. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Cuando transmitas una app, todo lo que se muestre o reproduzcas en ella será visible. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Transmitir pantalla"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"¿Quieres empezar a compartir?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Cuando compartas, grabes o transmitas contenido, Android podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Cuando compartas, grabes o transmitas una app, Android podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Iniciar"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Siguiente"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"El uso compartido se detiene al cambiar de app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Compartir esta app en su lugar"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Cambiar de cuenta"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilidad"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Combinaciones de teclas"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Buscar combinaciones de teclas"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"La búsqueda no arrojó resultados"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícono de contraer"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícono de expandir"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir a la pantalla principal"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Listo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para volver, desliza tres dedos hacia la derecha o la izquierda en cualquier lugar del panel táctil.\n\nPara completar esta acción, también puedes usar la combinación de teclas Action + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a la página principal"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir a la pantalla principal en cualquier momento, desliza hacia arriba desde la parte inferior de la pantalla con tres dedos."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil en el que aparecen tres dedos que se mueven hacia la derecha y la izquierda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla de un dispositivo en la que aparece una animación del gesto atrás"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla principal, desliza hacia arriba con tres dedos en el panel táctil"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las apps recientes, desliza hacia arriba con tres dedos y mantén presionado el panel táctil"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas las apps, presiona la tecla de acción en el teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Oculto"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea el dispositivo para ver"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para ir hacia atrás"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o la derecha con tres dedos. Presiona para aprender más gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla principal"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba con tres dedos y mantenlos presionados. Presiona para aprender más gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Presiona la tecla de acción en cualquier momento. Presiona para aprender más gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La atenuación extra ahora es parte de la barra de brillo"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ahora puedes bajar el nivel del brillo desde la parte superior de la pantalla para atenuarla aún más.\n\nEsto funciona mejor si estás en un ambiente oscuro."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Quitar la combinación de teclas de atenuación extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Se quitó el atajo de atenuación extra. Para bajar el brillo, usa la barra de brillo normal."</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 3aff0fa85b7c..a31fec735347 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Grabación de pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"¿Empezar a grabar?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Mientras grabas contenido, Android puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Mientras grabas una aplicación, Android puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Empezar a grabar"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabar audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sonido de tu dispositivo, como música, llamadas y tonos de llamada"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotipo de la aplicación"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Reintentar"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca para cancelar la autenticación"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Haz clic para emparejar un nuevo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se ha podido actualizar el preajuste"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preajuste"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtítulos automáticos"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítulos automáticos"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"¿Desbloquear el micrófono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"¿Desbloquear la cámara del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"¿Desbloquear la cámara y el micrófono del dispositivo?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ajustes"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestionar en los ajustes"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hay modos activos}=1{{mode} está activo}many{Hay # modos activos}other{Hay # modos activos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas, los recordatorios, los eventos y las llamadas que especifiques. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • En <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> terminará de cargarse"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets en la pantalla de bloqueo"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> añadido a la pantalla de bloqueo"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Cerrar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tendrá acceso a toda la información que se muestre en la pantalla o se reproduzca en el dispositivo mientras grabas o envías contenido, incluidos contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"¿Empezar a grabar o enviar contenido?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que ofrece esta función tendrá acceso a toda la información que se muestre en la pantalla o se reproduzca en el dispositivo mientras grabas o envías contenido, incluidos contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Toda la pantalla"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Una sola aplicación"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Compartir o grabar una aplicación"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"¿Empezar a grabar o enviar contenido con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cuando compartes, grabas o envías contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cuando compartes, grabas o envías una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Empezar"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Compartir tu pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una aplicación"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda la pantalla"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes toda tu pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que hay en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que se muestra o reproduce en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha inhabilitado esta opción"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Empezar a enviar?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cuando envías contenido, Android puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cuando envías una aplicación, Android puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Empezar a enviar"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"¿Enviar tu pantalla?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Enviar solo una aplicación"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Enviar toda la pantalla"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Cuando envías toda tu pantalla, se ve todo lo que hay en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Cuando envías una aplicación, se ve todo lo que se muestre o reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Enviar pantalla"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"¿Empezar a compartir?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Cuando compartes, grabas o envías contenido, Android puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Cuando compartes, grabas o envías una aplicación, Android puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Empezar"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Siguiente"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"El uso compartido se detiene al cambiar de aplicación"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Compartir esta aplicación"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Volver"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilidad"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Combinaciones de teclas"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atajos de búsqueda"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No hay resultados de búsqueda"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icono de contraer"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icono de desplegar"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir al inicio"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hecho"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"¡Bien hecho!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil con tres dedos moviéndose hacia la derecha y la izquierda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla del dispositivo que muestra una animación del gesto para volver atrás"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para volver, desliza con tres dedos hacia la izquierda o la derecha en cualquier parte del panel táctil.\n\nTambién puedes hacerlo con la combinación de teclas asignada + Esc."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"¡Bien hecho!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Has completado el gesto para volver."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a Inicio"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir a la pantalla de inicio en cualquier momento, desliza hacia arriba con tres dedos desde la parte inferior de la pantalla."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"¡Muy bien!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Has completado el gesto para ir a la pantalla de inicio."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de acción"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acceder a tus aplicaciones, pulsa la tecla de acción de tu teclado."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"¡Enhorabuena!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Has completado el gesto de la tecla de acción.\n\nLa combinación de teclas Acción + / muestra todas las combinaciones de teclas que tienes disponibles."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir a la pantalla de inicio, desliza hacia arriba con tres dedos en el panel táctil"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver las aplicaciones recientes, desliza hacia arriba y mantén pulsado el panel táctil con tres dedos"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas tus aplicaciones, pulsa la tecla de acción de tu teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Oculta"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea para ver"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa el panel táctil para volver atrás"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Desliza hacia la izquierda o hacia la derecha con tres dedos. Toca para aprender a usar más gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa el panel táctil para ir a la pantalla de inicio"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba y mantén pulsado con tres dedos. Toca para aprender a usar más gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las aplicaciones"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pulsa la tecla de acción en cualquier momento. Toca para aprender a usar más gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La atenuación extra ahora forma parte de la barra de brillo"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ahora puedes atenuar aún más tu pantalla reduciendo el nivel de brillo desde la parte superior.\n\nFunciona mejor cuando estás en un lugar con poca luz."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Eliminar acceso directo a la atenuación extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Acceso directo a la atenuación extra eliminado. Para reducir el brillo, usa la barra de brillo normal."</string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 5b38ff61e5d4..ff8ea04c6ecf 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekraanisalvesti"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Kas alustada salvestamist?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Salvestamise ajal on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Rakenduse salvestamise ajal on Androidil juurdepääs kõigele, mis on selles rakenduses nähtaval või mida selles esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Alusta salvestamist"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Salvesta heli"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Seadme heli"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Seadmest pärinev heli, nt muusika, kõned ja helinad"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Saada"</string> <string name="cancel" msgid="1089011503403416730">"Tühista"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Rakenduse logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Kinnita"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Proovi uuesti"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Puudutage autentimise tühistamiseks"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Uue seadme sidumiseks klõpsake"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Eelseadistust ei saanud värskendada"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Eelseadistus"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Reaalajas subtiitrid"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Reaalajas subtiitrid"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kas tühistada seadme mikrofoni blokeerimine?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kas tühistada seadme kaamera blokeerimine?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kas tühistada seadme kaamera ja mikrofoni blokeerimine?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Seaded"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Väljas"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Seadistamine"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Seadetes halamine"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aktiivsed režiimid puuduvad}=1{{mode} on aktiivne}other{# režiimi on aktiivsed}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Helid ja värinad ei sega teid. Kuulete siiski enda määratud äratusi, meeldetuletusi, sündmusi ja helistajaid. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Helid ja värinad ei sega teid. Kuulete siiski äratusi. Samuti kuulete kõike, mille esitamise ise valite, sh muusika, videod ja mängud."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Kohanda"</string> @@ -478,15 +483,14 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Aeglane laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Lukustuskuva vidinad"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g> lisati lukustuskuvale"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohandage"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobuge"</string> - <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lisage ja eemaldage selles ruumis oma vidinaid ning muutke nende järjestust"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lisage ja eemaldage vidinaid ning muutke nende järjestust"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisage rohkem vidinaid"</string> <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vajutage pikalt vidinate kohandamiseks"</string> - <string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Kohanda vidinaid"</string> + <string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Vidinate kohandamine"</string> <string name="unlock_reason_to_customize_widgets" msgid="5011909432460546033">"Avage vidinate kohandamiseks"</string> <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Keelatud vidina rakenduseikoon"</string> <string name="icon_description_for_pending_widget" msgid="8413816401868001755">"Installitava vidina rakenduseikoon"</string> @@ -501,7 +505,7 @@ <string name="work_mode_off_title" msgid="5794818421357835873">"Kas lõpetada töörakenduste peatamine?"</string> <string name="work_mode_turn_on" msgid="907813741770247267">"Lõpeta peatamine"</string> <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Lukustuskuva vidinate sulgemine"</string> - <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Kohanda vidinaid"</string> + <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Vidinate kohandamine"</string> <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Lukustuskuva vidinad"</string> <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"vidina valimine"</string> <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"eemaldage vidin"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Rakendus <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Kas alustada salvestamist või ülekannet?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Seda funktsiooni pakkuv teenus saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Kogu ekraanikuva"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Üks rakendus"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Rakenduse jagamine või salvestamine"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Kas alustada rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> salvestamist või ülekannet?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kui jagate, salvestate või kannate üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kui jagate, salvestate või kannate rakendust üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite, fotode, heli ja videoga ettevaatlik."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Alusta"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kas jagada teie ekraani rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaga üht rakendust"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaga kogu ekraani"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kogu ekraanikuva jagamisel on kogu sellel kuvatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Rakenduse jagamisel on kogu rakenduses kuvatav või esitatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaga ekraani"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> on selle valiku keelanud"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Kas alustada ülekandmist?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kui kannate üle, on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Rakenduse ülekandmise ajal on Androidil juurdepääs kõigele, mis on selles rakenduses nähtaval või mida selles esitatakse. Seega olge paroolide, makseteabe, sõnumite, fotode, heli ja videoga ettevaatlik."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Alusta ülekandmist"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Kas kanda ekraanikuva üle?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Ühe rakenduse ülekandmine"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Kogu ekraanikuva ülekandmine"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kogu ekraanikuva ülekandmisel on kogu sellel kuvatav sisu nähtav. Seega olge ettevaatlik näiteks paroolide, makseteabe, sõnumite, fotode ning heli ja videoga."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Rakenduse ülekandmisel on kogu rakenduses kuvatav või esitatav sisu nähtav. Seega olge ettevaatlik näiteks paroolide, makseteabe, sõnumite, fotode ning heli ja videoga."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Kanna üle ekraanikuva"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Kas alustada jagamist?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kui jagate, salvestate või kannate üle, on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kui jagate, salvestate või kannate rakendust üle, on Androidil juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite, fotode, heli ja videoga ettevaatlik."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Alusta"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Järgmine"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Rakenduste vahetamisel jagamine peatatakse"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Jaga hoopis seda rakendust"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Lülitu tagasi"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Juurdepääsetavus"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klaviatuuri otseteed"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Otsingu otseteed"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Otsingutulemused puuduvad"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ahendamisikoon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laiendamisikoon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"või"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Avakuvale liikumise liigutus"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toiminguklahv"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Väga hea!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tagasi"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale.\n\nSamuti saate selle jaoks kasutada klaviatuuri otseteed toiminguklahv + paoklahv."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Avalehele"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Mis tahes ajal avakuvale liikumiseks pühkige kolme sõrmega ekraanikuva allosast üles."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Puuteplaat kolme paremale ja vasakule liikuva sõrmega"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Seadme ekraanil näidatakse tagasiliigutuse animatsiooni"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatuuri taustavalgustus"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tase %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodu juhtelemendid"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Avakuvale liikumiseks pühkige puuteplaadil kolme sõrmega üles"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Hiljutiste rakenduste kuvamiseks pühkige puuteplaadil kolme sõrmega üles ja hoidke sõrmi puuteplaadil"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Kõigi oma rakenduste kuvamiseks vajutage klaviatuuril toiminguklahvi"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Peidetud"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Vaatamiseks avage"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Puuteplaadi kasutamine tagasiliikumiseks"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Pühkige kolme sõrmega vasakule või paremale. Puudutage žestide kohta lisateabe saamiseks."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Puuteplaadi kasutamine avakuvale liikumiseks"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pühkige kolme sõrmega üles ja hoidke sõrmi plaadil. Puudutage žestide kohta lisateabe saamiseks."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatuuri kasutamine kõigi rakenduste kuvamiseks"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Vajutage soovitud ajal toiminguklahvi. Puudutage žestide kohta lisateabe saamiseks."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funktsioon „Eriti tume“ on nüüd osa ereduse reguleerimise ribast"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nüüd saate muuta ekraani eriti tumedaks, vähendades ereduse taset ekraani ülaosast veelgi rohkem.\n\nSee toimib kõige paremini hämaras keskkonnas."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Eemalda funktsiooni „Eriti tume“ otsetee"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Funktsiooni „Eriti tume“ otsetee eemaldati. Kasutage ereduse vähendamiseks tavapärast ereduse reguleerimise riba."</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 6471c3bc131d..51c15934a786 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Pantaila-grabagailua"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Grabatzen hasi nahi duzu?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Grabatzen duzunean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Aplikazio bat grabatzen duzunean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Hasi grabatzen"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabatu audioa"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Gailuaren audioa"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Gailuko soinuak; adibidez, musika, deiak eta tonuak"</string> @@ -126,7 +136,7 @@ <string name="screenrecord_save_text" msgid="3008973099800840163">"Sakatu ikusteko"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"Errore bat gertatu da pantaila-grabaketa gordetzean"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Errore bat gertatu da pantaila grabatzen hastean"</string> - <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Grabaketa gelditu nahi duzu?"</string> + <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Grabatzeari utzi nahi diozu?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Pantaila osoa grabatzen ari zara"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"<xliff:g id="APP_NAME">%1$s</xliff:g> grabatzen ari zara"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Utzi grabatzeari"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Bidali"</string> <string name="cancel" msgid="1089011503403416730">"Utzi"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Aplikazioaren logotipoa"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Berretsi"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Saiatu berriro"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Sakatu hau autentifikazioa bertan behera uzteko"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Egin klik beste gailu bat parekatzeko"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ezin izan da eguneratu aurrezarpena"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Aurrezarpena"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Istanteko azpitituluak"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Istanteko azpitituluak"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Gailuaren mikrofonoa desblokeatu nahi duzu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Gailuaren kamera desblokeatu nahi duzu?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Gailuaren kamera eta mikrofonoa desblokeatu nahi dituzu?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ezarpenak"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desaktibatuta"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfiguratu"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Kudeatu ezarpenetan"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ez dago modurik aktibo}=1{{mode} aktibo dago}other{# modu aktibo daude}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak, gertaera eta abisuen tonuak, eta aukeratzen dituzun deitzaileen dei-tonuak joko ditu. Bestalde, zuk erreproduzitutako guztia entzungo duzu, besteak beste, musika, bideoak eta jokoak."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Gailuak ez du egingo ez soinurik ez dardararik, baina alarmak joko ditu. Hala ere, zuk erreproduzitutako guztia entzun ahal izango duzu, besteak beste, musika, bideoak eta jokoak."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Pertsonalizatu"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mantso kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pantaila blokeatuko widgetak"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta gehitu da pantaila blokeatuan"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pertsonalizatu"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Baztertu"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Grabatzen edo igortzen hasi nahi duzu?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia erabili ahalko du funtzio hori eskaintzen duen zerbitzuak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Pantaila osoa"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Aplikazio bakar bat"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partekatu edo grabatu aplikazio bat"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin grabatzen edo igortzen hasi nahi duzu?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Hasi"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin pantaila partekatu nahi duzu?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partekatu aplikazio bat"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partekatu pantaila osoa"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pantaila osoa partekatzen ari zarenean, pantailan duzun guztia ikus dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Aplikazio bat partekatzen ari zarenean, aplikazio horretan agertzen den edo bertan erreproduzitzen ari den guztia ikusi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partekatu pantaila"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak aukera desgaitu du"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Igortzen hasi nahi duzu?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Edukia igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Aplikazio bat igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Hasi igortzen"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Pantaila igorri nahi duzu?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Igorri aplikazio bat"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Igorri pantaila osoa"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Pantaila osoa igortzen ari zarenean, pantailan duzun guztia dago ikusgai. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Aplikazio bat igortzen ari zarenean, aplikazio horretan agertzen den edo bertan erreproduzitzen ari den guztia dago ikusgai. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Igorri pantaila"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Partekatzen hasi nahi duzu?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Hasi"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Hurrengoa"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Partekatzea pausatu egiten da aplikazioz aldatzean"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Partekatu aplikazioa"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Itzuli"</string> @@ -612,7 +624,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikusi eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPNa"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent bidez desblokeatuta"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Blokeatu egin da gailua. Autentifikatze-saiakera gehiegi egin dira."</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Blokeatu egin da gailua. Autentifikatzeko saiakera gehiegi egin dira."</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Gailua blokeatuta dago\nEzin izan da autentifikatu"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Soinuaren ezarpenak"</string> @@ -970,7 +982,7 @@ <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> (<xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>)"</string> <string name="wifi_is_off" msgid="5389597396308001471">"Wifi-konexioa desaktibatuta dago"</string> - <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth bidezko konexioa desaktibatuta dago"</string> + <string name="bt_is_off" msgid="7436344904889461591">"Bluetootha desaktibatuta dago"</string> <string name="dnd_is_off" msgid="3185706903793094463">"Ez molestatzeko modua desaktibatuta dago"</string> <string name="dnd_is_on" msgid="7009368176361546279">"Aktibatuta dago ez molestatzeko modua"</string> <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Ez molestatzeko modua aktibatu du arau automatiko batek (<xliff:g id="ID_1">%s</xliff:g>)."</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Erabilerraztasuna"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Lasterbideak"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Bilatu lasterbideak"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ez dago bilaketa-emaitzarik"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tolesteko ikonoa"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Zabaltzeko ikonoa"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"edo"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Orri nagusira joateko keinua"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Ekintza-tekla"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Eginda"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bikain!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Egin atzera"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Atzera egiteko, pasatu 3 hatz ezkerrera edo eskuinera ukipen-panelean.\n\nEkintza + Ihes lasterbidea ere erabil dezakezu horretarako."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Joan orri nagusira"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Orri nagusira joateko, pasatu 3 hatz pantailaren behealdetik gora."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 hatz ukipen-panel baten gainean eskuinera eta ezkerrera mugitzen erakusten duen irudia"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Gailuaren pantailan atzera egiteko keinuaren animazioa erakusten duen irudia"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d/%2$d maila"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuen kontrola"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Hasierako pantailara joateko, pasatu 3 hatz ukipen-pantailan"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Azkenaldiko aplikazioak ikusteko, pasatu 3 hatz ukipen-panelean gora eta eduki sakatuta"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aplikazio guztiak ikusteko, sakatu teklatuko ekintza-tekla"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Desitxuratuta"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desblokeatu ikusteko"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Erabili ukipen-panela atzera egiteko"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Pasatu 3 hatz ezkerrera edo eskuinera. Sakatu keinu gehiago ikasteko."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Erabili ukipen-panela hasierako pantailara joateko"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasatu 3 hatz gora eta eduki sakatuta. Sakatu keinu gehiago ikasteko."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Erabili teklatua aplikazio guztiak ikusteko"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Sakatu ekintza-tekla edonoiz. Sakatu keinu gehiago ikasteko."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Orain, argitasun-barran agertzen da Are ilunago"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Orain, pantaila are ilunago jar dezakezu, pantailaren goialdetik argitasun-maila are gehiago jaitsita.\n\nIngurune ilun batean zaudenean funtzionatzen du ondoen."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Kendu Are ilunago eginbidearen lasterbidea"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kendu da Are ilunago eginbidearen lasterbidea. Argitasuna murrizteko, erabili argitasun-barra arrunta."</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index f4b9d9ea000c..a54939e72e45 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ضبطکن صفحهنمایش"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحهنمایش"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحهنمایش"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ضبط شروع شود؟"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"درحین ضبط کردن، Android به همه محتوایی که در صفحهتان نمایان است یا در دستگاهتان پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"درحین ضبط کردن برنامه، Android به همه محتوایی که در آن برنامه نمایان است یا پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"شروع ضبط"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ضبط صدا"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"صدای دریافتی از دستگاه"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"صدای دریافتی از دستگاه، مثل موسیقی، تماس، و آهنگ زنگ"</string> @@ -130,8 +140,8 @@ <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"اکنون درحال ضبط کل صفحهنمایشتان هستید"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"اکنون درحال ضبط <xliff:g id="APP_NAME">%1$s</xliff:g> هستید"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"توقف ضبط"</string> - <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"درحال همرسانی صفحهنمایش"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"صفحه همرسانی متوقف شود؟"</string> + <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"درحال همرسانی صفحه"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"همرسانی صفحه متوقف شود؟"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"اکنون درحال همرسانی کل صفحهنمایشتان با <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> هستید"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"اکنون درحال همرسانی کل صفحهنمایشتان با یک برنامه هستید"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"اکنون درحال همرسانی <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> هستید"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ارسال"</string> <string name="cancel" msgid="1089011503403416730">"لغو"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"نشانواره برنامه"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"تأیید"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"امتحان مجدد"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"برای لغو راستیآزمایی تکضرب بزنید"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"برای جفت کردن دستگاه جدید، کلیک کنید"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"پیشتنظیم بهروزرسانی نشد"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"پیشتنظیم"</string> - <string name="live_caption_title" msgid="8916875614623730005">"زیرنویس ناشنوایان زنده"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"زیرنویس ناشنوایان زنده"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"میکروفون دستگاه لغو انسداد شود؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"دوربین دستگاه لغو انسداد شود؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"دوربین و میکروفون دستگاه لغو انسداد شود؟"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"تنظیمات"</string> <string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string> <string name="zen_mode_off" msgid="1736604456618147306">"خاموش"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"راهاندازی"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"مدیریت در تنظیمات"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{حالت فعالی وجود ندارد}=1{{mode} فعال است}one{# حالت فعال است}other{# حالت فعال است}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"بهجز هشدارها، یادآوریها، رویدادها و تماسگیرندگانی که خودتان مشخص میکنید، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"بهجز هشدارها، هیچ صدا و لرزشی نخواهید داشت. همچنان صدای مواردی را که پخش میکنید میشنوید (ازجمله صدای موسیقی، ویدیو و بازی)."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"سفارشی کردن"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ کردن آهسته • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ابزارکها در صفحه قفل"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"ابزاره <xliff:g id="WIDGET_NAME">%1$s</xliff:g> به صفحه قفل اضافه شد"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گامبهگام عمومی، تند بهچپ بکشید"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"سفارشیسازی"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"بستن"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ضبط یا پخش محتوا شروع شود؟"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"سرویس ارائهدهنده این عملکرد به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"کل صفحه"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"یک برنامه"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"همرسانی یا ضبط برنامه"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"ضبط یا پخش محتوا با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع شود؟"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"وقتی درحال همرسانی، ضبط، یا پخش محتوا هستید، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه محتوایی که در صفحهتان نمایان است یا در دستگاهتان پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"وقتی درحال همرسانی، ضبط، یا پخش محتوای برنامهای هستید، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه محتوایی که در آن برنامه نمایان است یا پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"شروع"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"صفحهنمایش با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> همرسانی شود؟"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"همرسانی یک برنامه"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"همرسانی کل صفحهنمایش"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"وقتی کل صفحهنمایش را همرسانی میکنید، هر چیزی که روی صفحهنمایش شما وجود داشته باشد برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابلمشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"وقتی برنامهای را همرسانی میکنید، هر چیزی که در آن برنامه نمایش داده شود یا پخش شود برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابلمشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"همرسانی صفحهنمایش"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>این گزینه را غیرفعال کرده است"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"پخش محتوا شروع شود؟"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"وقتی محتوا پخش میکنید، Android به همه محتوایی که در صفحهتان نمایان است یا در دستگاهتان پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"وقتی محتوای برنامهای را پخش میکنید، Android به همه محتوایی که در آن برنامه نمایان است یا پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"شروع پخش محتوا"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"محتوای صفحهنمایش شما پخش شود؟"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"پخش کردن محتوای یک برنامه"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"پخش کردن محتوای کل صفحه"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"وقتی محتوای کل صفحهنمایش را پخش میکنید، هر چیزی که روی صفحهنمایش شما وجود دارد قابلمشاهده است. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"وقتی محتوای برنامهای را پخش میکنید، هر چیزی که در آن برنامه پخش میشود قابلمشاهده است. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"پخش محتوای صفحهنمایش"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"همرسانی شروع شود؟"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"وقتی درحال همرسانی، ضبط، یا پخش محتوا هستید، Android به همه محتوایی که در صفحهتان نمایان است یا در دستگاهتان پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"وقتی درحال همرسانی، ضبط، یا پخش محتوای برنامهای هستید، Android به همه محتوایی که در آن برنامه نمایان است یا پخش میشود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"شروع"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"بعدی"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"وقتی برنامهها را تغییر میدهید، همرسانی متوقف میشود"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"درعوض همرسانی این برنامه"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"تغییر به حالت قبل"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"دسترسپذیری"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"میانبرهای صفحهکلید"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"جستجوی میانبرها"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"نتیجهای برای جستجو پیدا نشد"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"نماد جمع کردن"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"نماد ازهم بازکردن"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"اشاره صفحه اصلی"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"دکمه کنش"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تمام"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"عالی است!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"برگشتن"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"برای برگشتن، در هر جایی از صفحه لمسی، با سه انگشت تند بهچپ یا راست بکشید.\n\nبرای این کار میتوانید از میانبر صفحهکلید «کنش + گریز» هم استفاده کنید."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"رفتن به صفحه اصلی"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"برای رفتن به صفحه اصلی در هرزمانی، با سه انگشت از پایین صفحهنمایش تند بهبالا بکشید."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"صفحه لمسی که سه انگشت را درحال حرکت بهسمت راست و چپ نشان میدهد"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"صفحهنمایش دستگاه درحال نمایش پویانمایی مربوط به اشاره برگشتن"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پسزمینه صفحهکلید"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"سطح %1$d از %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل خانه هوشمند"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"برای رفتن به صفحه اصلی، در صفحه لمسی با سه انگشت تند بهبالا بکشید"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"برای مشاهده برنامههای اخیر، در صفحه لمسی با سه انگشت تند بهبالا بکشید و نگه دارید"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"برای مشاهده همه برنامهها، دکمه کنش در صفحهکلید را فشار دهید"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"محوشده"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"برای مشاهده، قفل را باز کنید"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"برای برگشتن از صفحه لمسی استفاده کنید"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"با سه انگشت تند بهچپ یا راست بکشید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"برای رفتن به صفحه اصلی از صفحه لمسی استفاده کنید"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"با سه انگشت تند بهبالا بکشید و نگه دارید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"برای مشاهده همه برنامهها، از صفحهکلید استفاده کنید"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"در هرزمانی دکمه کنش را فشار دهید. برای آشنایی با اشارههای بیشتر، تکضرب بزنید."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"«بسیار کمنور» اکنون بخشی از نوار روشنایی است"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ازاینپس میتوانید با پایینتر آوردن سطح روشنایی از بالای صفحهنمایش، صفحهنمایش را بسیار کمنور کنید.\n\nاین ویژگی زمانی بهترین عملکرد را دارد که در محیطی تاریک باشید."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"حذف میانبر «بسیار کمنور»"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"میانبر «بسیار کمنور» حذف شد. برای کم کردن روشنایی، از نوار معمول روشنایی استفاده کنید."</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 79962f01846f..f3eab4750815 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Näytön tallentaja"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Aloitetaanko tallennus?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Kun tallennat, Android saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kun striimaat sovellusta, Android saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, audiota tai videoita."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Aloita tallennus"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Tallenna audiota"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Laitteen audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Musiikki, puhelut, soittoäänet ja muut äänet laitteesta"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Lähetä"</string> <string name="cancel" msgid="1089011503403416730">"Peru"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Sovelluksen logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Vahvista"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Yritä uudelleen"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Peru todennus napauttamalla"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Muodosta uusi laitepari klikkaamalla"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Esiasetusta ei voitu muuttaa"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Esiasetus"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Livetekstitys"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Livetekstitys"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kumotaanko laitteen mikrofonin esto?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kumotaanko laitteen kameran esto?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kumotaanko laitteen kameran ja mikrofonin esto?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Asetukset"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Pois päältä"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Ota käyttöön"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Muuta asetuksista"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ei aktiivisia tiloja}=1{{mode} on aktiivinen}other{# tilaa on aktiivisena}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä, muistutuksia, tapahtumia tai määrittämiäsi soittajia. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Äänet ja värinät eivät häiritse sinua, paitsi jos ne ovat hälytyksiä. Kuulet edelleen kaiken valitsemasi sisällön, kuten musiikin, videot ja pelit."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Muokkaa"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu hitaasti • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetit lukitusnäytöllä"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ‑widget lisätty lukitusnäyttöön"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Muokkaa"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hylkää"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Aloitetaanko tallentaminen tai striimaus?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ominaisuuden tarjoavalla palvelulla on pääsy kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Koko näyttö"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Yksittäinen sovellus"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Jaa sovellus tai tallenna sen sisältöä"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Haluatko, että <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aloittaa tallennuksen tai striimauksen?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kun jaat, tallennat tai striimaat, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kun jaat, tallennat tai striimaat sovellusta, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Aloita"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Saako <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> nähdä näyttösi?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaa yksi sovellus"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaa koko näyttö"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kun jaat koko näytön, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sen sisälllön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kun jaat sovelluksen, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sovelluksessa näkyvän tai toistetun sisällön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaa näyttö"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> on poistanut vaihtoehdon käytöstä"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Aloitetaanko striimaus?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kun striimaat, Android saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kun striimaat sovellusta, Android saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Aloita striimaus"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Striimataanko näyttö?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Striimaa yksi sovellus"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Striimaa koko näyttö"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kun striimaat koko näyttöä, kaikki näytön sisältö on näkyvillä. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kun striimaat sovellusta, kaikki sovelluksessa näkyvä tai toistettu sisältö on näkyvillä. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Striimaa näyttö"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Aloitetaanko jakaminen?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kun jaat, tallennat tai striimaat, Android saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kun jaat, tallennat tai striimaat, Android saa pääsyn kaikkeen sovelluksella näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Aloita"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Seuraava"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Jakaminen keskeytyy, kun vaihdat sovelluksia"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Jaa tämä sovellus"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Vaihda takaisin"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Saavutettavuus"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Pikanäppäimet"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Pikahaut"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ei hakutuloksia"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tiivistyskuvake"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laajennuskuvake"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"tai"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Etusivu-ele"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toimintonäppäin"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Hienoa!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Takaisin"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella.\n\nVoit myös käyttää pikanäppäinyhdistelmää toimintonäppäin + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Siirry etusivulle"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Voit siirtyä aloitusnäytölle milloin tahansa pyyhkäisemällä ylös näytön alareunasta kolmella sormella."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Kosketuslevy, jolla kolme sormea liikkuu oikealle ja vasemmalle"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Laitteen näyttö, jolla näkyy animaatio takaisin-eleestä"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Näppämistön taustavalo"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Taso %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodin ohjaus"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Jos haluat siirtyä aloitussivulle, pyyhkäise kosketuslevyllä ylös kolmella sormella"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Näet äskeiset sovellukset, kun pyyhkäiset ylös ja pidät kosketuslevyä painettuna kolmella sormella."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Jos haluat nähdä kaikki sovellukset, paina näppäimistön toimintonäppäintä"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Sensuroitu"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Avaa lukitus ja katso tiedot"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Takaisin siirtyminen kosketuslevyn avulla"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Pyyhkäise vasemmalle tai oikealle kolmella sormella. Lue lisää eleistä napauttamalla."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Aloitusnäytölle siirtyminen kosketuslevyn avulla"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella. Lue lisää eleistä napauttamalla."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kaikkien sovellusten näkeminen näppäimistön avulla"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Voit painaa toimintonäppäintä milloin tahansa. Lue lisää eleistä napauttamalla."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Erittäin himmeä on nyt osa kirkkauspalkkia"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Voit nyt tehdä näytöstä erittäin himmeän vähentämällä kirkkautta vieläkin enemmän näytön yläreunasta.\n\nTämä toimii parhaiten pimeässä ympäristössä."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Poista erittäin himmeä ‑pikakomento"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Erittäin himmeä ‑pikakomento poistettu. Voit vähentää kirkkautta tavallisesta kirkkauspalkista."</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index f34ce9811a99..7c091c7246db 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Commencer l\'enregistrement?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Pendant l\'enregistrement, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Lorsque vous enregistrez une appli, Android a accès à tout ce qui est visible ou lu sur cette appli. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Commencer l\'enregistrement"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Enregistrer des fichiers audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio de l\'appareil"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons de l\'appareil comme la musique, les appels et les sonneries"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envoyer"</string> <string name="cancel" msgid="1089011503403416730">"Annuler"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo de l\'appli"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmer"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Réessayer"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Touchez ici pour annuler l\'authentification"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquez ici pour associer un nouvel appareil"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour le préréglage"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Préréglage"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Sous-titres instantanés"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sous-titres instantanés"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le microphone de l\'appareil?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer l\'appareil photo de l\'appareil?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le microphone?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurer"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gérer dans les paramètres"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aucun mode actif}=1{Le mode {mode} est actif}one{# mode est actif}many{# de modes sont actifs}other{# modes sont actifs}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes, les rappels, les événements et les appelants que vous sélectionnez. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personnaliser"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> • Terminée <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Ajout du widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> à l\'écran de verrouillage"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aura accès à toute l\'information qui est visible sur votre écran ou lue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et les contenus audio que vous faites jouer."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Commencer à enregistrer ou à diffuser?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou lu sur votre appareil pendant que vous enregistrez ou diffusez. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Écran entier"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Une seule appli"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partager ou enregistrer une appli"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Commencer à enregistrer ou à diffuser avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Lorsque vous partagez, enregistrez ou diffusez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lorsque vous partagez, enregistrez ou diffusez une appli, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur cette appli. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Commencer"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager l\'intégralité de l\'écran"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez l\'intégralité de votre écran, tout ce qui s\'y trouve est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui s\'y affiche ou s\'y joue est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a désactivé cette option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Commencer la diffusion?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Lorsque vous diffusez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lorsque vous diffusez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur cette appli. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Commencer la diffusion"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Diffuser votre écran?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Diffuser une appli"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Diffuser l\'intégralité de l\'écran"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Lorsque vous diffusez l\'intégralité de votre écran, tout ce qui s\'y trouve est visible. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Lorsque vous diffusez une appli, tout ce qui s\'y affiche ou s\'y joue est visible. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Diffuser l\'écran"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Commencer à partager?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Lorsque vous partagez, enregistrez ou diffusez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Lorsque vous partagez, enregistrez ou diffusez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur cette appli. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Commencer"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Suivant"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Le partage s\'interrompt lorsque vous changez d\'appli"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Partager plutôt cette appli"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Revenir en arrière"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibilité"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Raccourcis-clavier"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Recherchez des raccourcis"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Aucun résultat de recherche"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste d\'accès à l\'écran d\'accueil"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bon travail!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile montrant trois doigts se déplaçant à droite et à gauche"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran de l\'appareil montrant l\'animation pour le geste de retour"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pour revenir en arrière, balayez vers la gauche ou la droite en utilisant trois doigts n\'importe où sur le pavé tactile.\n\nVous pouvez également utiliser le raccourci clavier Action+Échap."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bon travail!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Vous avez appris le geste de retour en arrière."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à la page d\'accueil"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pour accéder à votre écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut avec trois doigts."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bien!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Vous avez appris le geste de retour à l\'écran d\'accueil."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Touche d\'action"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Pour accéder à vos applis, appuyez sur la touche d\'action de votre clavier."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Félicitations!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Vous avez terminé le geste de la touche d\'action.\n\nAction + / affiche tous les raccourcis dont vous disposez."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Domotique"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour accéder à l\'écran d\'accueil, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez l\'écran vers le haut avec trois doigts sur le pavé tactile et maintenez-les en place"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Supprimé"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Déverrouiller pour afficher"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Utiliser votre pavé tactile pour revenir en arrière"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou vers la droite avec trois doigts. Touchez pour apprendre d\'autres gestes."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour accéder à l\'écran d\'accueil"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez l\'écran vers le haut avec trois doigts et maintenez-les en place. Touchez pour apprendre d\'autres gestes."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utiliser votre clavier pour afficher toutes les applis"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Touchez pour apprendre d\'autres gestes."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La réduction supplémentaire de la luminosité fait désormais partie de la barre de luminosité"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Vous pouvez désormais rendre l\'écran encore plus sombre en réduisant davantage le niveau de luminosité à partir du haut de l\'écran.\n\nCela fonctionne mieux lorsque vous êtes dans un environnement sombre."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Retirer le raccourci de réduction supplémentaire de la luminosité"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Le raccourci de réduction supplémentaire de la luminosité à été retiré. Pour réduire la luminosité, utilisez la barre de luminosité habituelle."</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index ad63e9e54e20..fea4cb6b090b 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Commencer à enregistrer ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Lorsque vous enregistrez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Lorsque vous enregistrez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Lancer l\'enregistrement"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Enregistrer l\'audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio de l\'appareil"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Son provenant de l\'appareil (musique, appels, sonneries, etc.)"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Envoyer"</string> <string name="cancel" msgid="1089011503403416730">"Annuler"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo de l\'appli"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmer"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Réessayer"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Appuyer pour annuler l\'authentification"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour les préréglages"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Préréglage"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Sous-titres instantanés"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sous-titres instantanés"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le micro de l\'appareil ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer la caméra de l\'appareil ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le micro de l\'appareil ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurer"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gérer dans les paramètres"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aucun mode actif}=1{{mode} est actif}one{# mode est actif}many{# de modes sont actifs}other{# modes sont actifs}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, comme la musique, les vidéos et les jeux."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personnaliser"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets sur l\'écran de verrouillage"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ajouté à l\'écran de verrouillage"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aura accès à toutes les informations visibles sur votre écran ou lues depuis votre appareil pendant un enregistrement ou une diffusion de contenu. Il peut s\'agir de mots de passe, détails de mode de paiement, photos, messages ou encore contenus audio lus."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Commencer à enregistrer ou à caster ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service qui fournit cette fonction aura accès à toutes les infos visibles sur votre écran ou lues depuis votre appareil pendant un enregistrement ou une diffusion de contenu. Il peut s\'agir de mots de passe, détails de mode de paiement, photos, messages ou encore contenus audio lus."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tout l\'écran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Uniquement l\'appli"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partager ou enregistrer une appli"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Commencer à enregistrer ou à caster avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Lorsque vous partagez, enregistrez ou castez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lorsque vous partagez, enregistrez ou castez une appli, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Commencer"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager tout l\'écran"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez tout votre écran, l\'ensemble de son contenu est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui est affiché ou lu dans celle-ci est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a désactivé cette option"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Commencer à caster ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Lorsque vous castez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lorsque vous castez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Commencer à caster"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Caster votre écran ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Caster une appli"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Caster tout l\'écran"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Lorsque vous castez tout votre écran, l\'ensemble de son contenu est visible. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Lorsque vous castez une appli, tout ce qui est affiché ou lu dans celle-ci est visible. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Caster l\'écran"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Commencer à partager ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Lorsque vous partagez, enregistrez ou castez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Lorsque vous partagez, enregistrez ou castez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Commencer"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Suivant"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Le partage est suspendu pendant le changement d\'application"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Partager cette application à la place"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Revenir"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibilité"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Raccourcis clavier"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Raccourcis de recherche"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Aucun résultat de recherche"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste Accueil"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bravo !"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pour revenir en arrière, balayez vers la gauche ou vers la droite avec trois doigts n\'importe où sur le pavé tactile.\n\nVous pouvez aussi utiliser le raccourci clavier Action+Échap pour cela."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à l\'accueil"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pour accéder à l\'écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut avec trois doigts."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pavé tactile sur lequel trois doigts glissent vers la droite, puis vers la gauche"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Écran d\'un appareil affichant l\'animation du geste Retour"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d sur %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Contrôle de la maison"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Pour revenir à l\'accueil, balayez vers le haut avec trois doigts sur le pavé tactile"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Pour afficher les applis récentes, balayez vers le haut avec trois doigts sur le pavé tactile et maintenez-les."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Pour afficher toutes vos applis, appuyez sur la touche d\'action de votre clavier"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Masqué"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Déverrouiller pour afficher"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Utilisez votre pavé tactile pour revenir en arrière"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Balayez vers la gauche ou la droite en utilisant trois doigts. Appuyez pour apprendre d\'autres gestes."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Utilisez votre pavé tactile pour revenir à l\'accueil"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez vers le haut en utilisant trois doigts et maintenez. Appuyez pour apprendre d\'autres gestes."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilisez votre clavier pour afficher toutes les applis"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Appuyez pour apprendre d\'autres gestes."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Luminosité ultra-réduite fait désormais partie de la barre de luminosité"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Désormais, vous pouvez rendre l\'écran encore plus sombre en abaissant davantage le niveau de luminosité en haut de l\'écran.\n\nCela fonctionne mieux lorsque vous êtes dans un environnement sombre."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Supprimer le raccourci Luminosité ultra-réduite"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Raccourci Luminosité ultra-réduite supprimé. Pour diminuer la luminosité, utilisez la barre de luminosité habituelle."</string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 913e589c1a33..1ee1ae355ca4 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Gravadora da pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Queres iniciar a gravación?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Durante a gravación, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Durante a gravación dunha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Iniciar gravación"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio do dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Son do dispositivo (por exemplo, música, chamadas e tons de chamada)"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotipo da aplicación"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar de novo"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toca para cancelar a autenticación"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic para vincular un novo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Non se puido actualizar a configuración predeterminada"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Configuración predeterminada"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtítulos instantáneos"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítulos instantáneos"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Queres desbloquear o micrófono do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Queres desbloquear a cámara do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Queres desbloquear a cámara e o micrófono do dispositivo?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Xestionar na configuración"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Non hai ningún modo activo}=1{{mode} está activo}other{Hai # modos activos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas, recordatorios, eventos e os emisores de chamada especificados. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Non te molestará ningún son nin vibración, agás os procedentes de alarmas. Seguirás escoitando todo aquilo que decidas reproducir, mesmo a música, os vídeos e os xogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando lentamente • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na pantalla de bloqueo"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Engadiuse o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> á pantalla de bloqueo"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Pechar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe datos como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Queres iniciar a gravación ou a emisión?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O servizo que proporciona esta función terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe datos como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Pantalla completa"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Unha soa aplicación"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Compartir ou gravar unha aplicación"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Queres comezar a gravar ou emitir contido con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cando compartes, gravas ou emites contido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cando compartes, gravas ou emites unha aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Queres compartir a pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir unha aplicación"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda a pantalla"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza nela. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza ou se reproduza nesa aplicación. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> desactivou esta opción"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Queres comezar a emitir contido?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cando emites contido, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cando emites unha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Comezar emisión"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Queres emitir a túa pantalla?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Emitir unha aplicación"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Emitir pantalla completa"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Cando emites a pantalla enteira, pódese ver todo o que haxa nela. Xa que logo, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Cando emites unha aplicación, pódese ver todo o que se mostre ou reproduza nela. Xa que logo, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Emitir pantalla"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Queres comezar a compartir contido?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Cando compartes, gravas ou emites contido, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Cando compartes, gravas ou emites unha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Iniciar"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Seguinte"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Cando cambias de aplicación, ponse en pausa o uso compartido"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Compartir esta aplicación"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Volver"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilidade"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Atallos de teclado"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atallos de busca"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Non hai resultados de busca"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona de contraer"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona de despregar"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Xesto para ir ao inicio"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Feito"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Moi ben!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Volver"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para retroceder, pasa tres dedos cara á esquerda ou cara á dereita en calquera parte do panel táctil.\n\nTamén podes usar o atallo de teclado Acción + Escape."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir ao inicio"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir á pantalla de inicio, pasa tres dedos cara arriba desde a parte inferior da pantalla."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Panel táctil que mostra tres dedos movéndose á dereita e á esquerda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Pantalla do dispositivo que mostra unha animación do xesto de retroceso"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controis domóticos"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para ir ao inicio, pasa tres dedos cara arriba no panel táctil"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver as aplicacións recentes, pasa tres dedos cara arriba no panel táctil e mantenos premidos"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas as aplicacións, preme a tecla de acción do teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Contido ocultado"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea o dispositivo para ver o contido"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa o panel táctil para volver"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Pasa tres dedos cara á esquerda ou cara á dereita. Toca para obter máis información sobre os xestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa o panel táctil para volver ao inicio"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasa tres dedos cara arriba e mantenos premidos. Toca para obter máis información sobre os xestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa o teclado para ver todas as aplicacións"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Preme a tecla de acción cando queiras. Toca para obter máis información sobre os xestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"A atenuación extra agora está incluída na barra de brillo"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora podes aumentar a atenuación da pantalla: só tes que baixar o nivel de brillo aínda máis desde a parte superior.\n\nEsta opción funciona mellor se estás nun ambiente escuro."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Quitar atallo de atenuación extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Quitouse o atallo de atenuación extra. Para reducir o brillo, usa a barra de brillo normal."</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 8fd8b3e9664d..49f472f6603e 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"સ્ક્રીન રેકોર્ડર"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"રેકોર્ડિંગ શરૂ કરીએ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"જ્યારે તમે રેકોર્ડ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી હોય કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી કોઈપણ વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"જ્યારે તમે કોઈ ઍપ રેકોર્ડ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"રેકોર્ડિંગ શરૂ કરો"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ઑડિયો રેકોર્ડ કરો"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ડિવાઇસનો ઑડિયો"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"મ્યુઝિક, કૉલ અને રિંગટોન જેવા તમારા ડિવાઇસના સાઉન્ડ"</string> @@ -138,7 +148,7 @@ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"તમે હાલમાં ઍપ શેર કરી રહ્યાં છો"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"શેર કરવાનું રોકો"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"સ્ક્રીન કાસ્ટ કરી રહ્યાં છીએ"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"શું કાસ્ટ કરવાનું બંધ કરીએ?"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"કાસ્ટ કરવાનું રોકીએ?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"તમે હાલમાં તમારી પૂર્ણ સ્ક્રીન <xliff:g id="DEVICE_NAME">%1$s</xliff:g> પર કાસ્ટ કરી રહ્યાં છો"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"તમે હાલમાં તમારી પૂર્ણ સ્ક્રીન નજીકના ડિવાઇસ પર કાસ્ટ કરી રહ્યાં છો"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"તમે હાલમાં <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>ને <xliff:g id="DEVICE_NAME">%2$s</xliff:g> પર કાસ્ટ કરી રહ્યાં છો"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"મોકલો"</string> <string name="cancel" msgid="1089011503403416730">"રદ કરો"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ઍપનો લોગો"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"કન્ફર્મ કરો"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ફરી પ્રયાસ કરો"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"પ્રમાણીકરણ રદ કરવા માટે ટૅપ કરો"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"નવા ડિવાઇસ સાથે જોડાણ કરવા માટે ક્લિક કરો"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"પ્રીસેટ અપડેટ કરી શક્યા નથી"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"પ્રીસેટ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"લાઇવ કૅપ્શન"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"લાઇવ કૅપ્શન"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ડિવાઇસના માઇક્રોફોનને અનબ્લૉક કરીએ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ડિવાઇસના કૅમેરાને અનબ્લૉક કરીએ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ડિવાઇસના કૅમેરા અને માઇક્રોફોનને અનબ્લૉક કરીએ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"સેટિંગ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"બંધ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"સેટઅપ કરો"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"સેટિંગમાં જઈને મેનેજ કરો"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{કોઈ સક્રિય મોડ નથી}=1{{mode} સક્રિય છે}one{# મોડ સક્રિય છે}other{# મોડ સક્રિય છે}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"અલાર્મ, રિમાઇન્ડર, ઇવેન્ટ અને તમે ઉલ્લેખ કરો તે કૉલર સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"અલાર્મ સિવાય તમને ધ્વનિ કે વાઇબ્રેશન દ્વારા ખલેલ પહોંચાડવામાં આવશે નહીં. સંગીત, વીડિઓ અને રમતો સહિત તમે જે કંઈપણ ચલાવવાનું પસંદ કરશો તે સંભળાતું રહેશે."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"કસ્ટમાઇઝ કરો"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ધીમેથી ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં ચાર્જ થઈ જશે"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"લૉક સ્ક્રીન પર વિજેટ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"લૉક સ્ક્રીન પર <xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ ઉમેરવામાં આવ્યું"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"કસ્ટમાઇઝ કરો"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"છોડી દો"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. આમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, મેસેજ અને તમે વગાડો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"શું રેકોર્ડ અથવા કાસ્ટ કરવાનું શરૂ કરીએ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, આ સુવિધા આપતી સેવાને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. જેમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, મેસેજ અને તમે વગાડો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"પૂર્ણ સ્ક્રીન"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"કોઈ એક ઍપ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"કોઈ ઍપ શેર કરો અથવા રેકોર્ડ કરો"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> વડે રેકોર્ડ અથવા કાસ્ટ કરવાનું શરૂ કરીએ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"જ્યારે તમે શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી હોય કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"જ્યારે તમે કોઈ ઍપ શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"શરૂ કરો"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> સાથે તમારી સ્ક્રીન શેર કરીએ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"એક ઍપ શેર કરો"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"સંપૂર્ણ સ્ક્રીન શેર કરો"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"જ્યારે તમે તમારી સંપૂર્ણ સ્ક્રીનને શેર કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પરની કોઈપણ વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"જ્યારે તમે કોઈ ઍપને શેર કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"સ્ક્રીન શેર કરો"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> દ્વારા આ વિકલ્પ બંધ કરવામાં આવ્યો છે"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"કાસ્ટ કરવાનું શરૂ કરીએ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"જ્યારે તમે કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી બધી વસ્તુઓનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"જ્યારે તમે ઍપને કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"કાસ્ટ કરવાનું શરૂ કરો"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"તમારી સ્ક્રીનને કાસ્ટ કરીએ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"એક ઍપને કાસ્ટ કરો"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"સંપૂર્ણ સ્ક્રીનને કાસ્ટ કરો"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"જ્યારે તમે તમારી સંપૂર્ણ સ્ક્રીનને કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પરની કોઈપણ વસ્તુ દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"જ્યારે તમે ઍપને કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુ દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"સ્ક્રીનને કાસ્ટ કરો"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"શેર કરવાનું શરૂ કરીએ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"જ્યારે તમે શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી હોય કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"જ્યારે તમે કોઈ ઍપ શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"શરૂ કરો"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"આગળ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"તમે ઍપ સ્વિચ કરો ત્યારે શેરિંગ થોભી જાય છે"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"તેના બદલે આ ઍપ શેર કરો"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"પાછળ સ્વિચ કરો"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ઍક્સેસિબિલિટી"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"કીબોર્ડ શૉર્ટકટ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"શૉર્ટકટ શોધો"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"કોઈ શોધ પરિણામો નથી"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\'નાનું કરો\'નું આઇકન"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\'મોટું કરો\'નું આઇકન"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"અથવા"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"હોમ સ્ક્રીન પર જવાનો સંકેત"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ઍક્શન કી"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"થઈ ગયું"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ખૂબ સરસ કામ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"પાછા જાઓ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"પાછા જવા માટે, ટચપૅડ પર ગમે ત્યાં ત્રણ આંગળી વડે ડાબે અથવા જમણે સ્વાઇપ કરો.\n\nઆના માટે તમે કીબોર્ડ શૉર્ટકટ Action + ESCનો ઉપયોગ કરી શકો છો."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"હોમ પર જાઓ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"કોઈપણ સમયે તમારી હોમ સ્ક્રીન પર જવા માટે, ત્રણ આંગળી વડે તમારી સ્ક્રીનની સૌથી નીચેની બાજુએથી ઉપરની તરફ સ્વાઇપ કરો."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"જમણી અને ડાબી તરફ ખસી રહેલી ત્રણ આંગળીઓ બતાવતું ટચપૅડ"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"પાછા જવા માટેના સંકેત માટેનું ઍનિમેશન બતાવતી ડિવાઇસ સ્ક્રીન"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"કીબોર્ડની બૅકલાઇટ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dમાંથી %1$d લેવલ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ઘરેલું સાધનોના નિયંત્રણો"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"હોમ સ્ક્રીન પર જવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"તાજેતરની ઍપ જોવા માટે, ટચપૅડ પર ત્રણ આંગળીઓ વડે ઉપર સ્વાઇપ કરો અને દબાવી રાખો"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"તમારી બધી ઍપ જોવા માટે, તમારા કીબોર્ડ પર ઍક્શન કી દબાવો"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"બદલાવેલું"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"જોવા માટે અનલૉક કરો"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"પાછા જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ત્રણ આંગળીનો ઉપયોગ કરીને ડાબે અથવા જમણે સ્વાઇપ કરો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"હોમ સ્ક્રીન પર જવા માટે તમારા ટચપૅડનો ઉપયોગ કરો"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ત્રણ આંગળીઓનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો અને દબાવી રાખો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"બધી ઍપ જોવા માટે તમારા કીબોર્ડનો ઉપયોગ કરો"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"કોઈપણ સમયે ઍક્શન કી દબાવો. સંકેતો વિશે વધુ જાણવા માટે ટૅપ કરો."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"બ્રાઇટનેસ બાર હવે એક્સ્ટ્રા ડિમનો ભાગ છે"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"તમે હવે તમારી સ્ક્રીનના સૌથી ઉપરના ભાગમાંથી બ્રાઇટનેસ લેવલને હજી પણ ઘટાડીને સ્ક્રીનને એક્સ્ટ્રા ડિમ બનાવી શકો છો.\n\nતમે ડાર્ક વાતાવરણમાં હો, ત્યારે આ શ્રેષ્ઠ રીતે કામ કરે છે."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખો"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખ્યો. તમારી બ્રાઇટનેસ ઘટાડવા માટે, નિયમિત બ્રાઇટનેસ બારનો ઉપયોગ કરો."</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 6d9637612dd9..9724bac819af 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रिकॉर्डर"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"क्या रिकॉर्डिंग शुरू करनी है?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"रिकॉर्ड करते समय, Android के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"किसी ऐप्लिकेशन को रिकॉर्ड करते समय, Android के पास उस ऐप्लिकेशन पर दिख रहे कॉन्टेंट या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"रिकॉर्ड करें"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ऑडियो रिकॉर्ड करें"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिवाइस ऑडियो"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"आपके डिवाइस से आने वाली आवाज़ जैसे कि संगीत, कॉल, और रिंगटोन"</string> @@ -126,19 +136,19 @@ <string name="screenrecord_save_text" msgid="3008973099800840163">"देखने के लिए टैप करें"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"स्क्रीन रिकॉर्डिंग सेव करते समय गड़बड़ी हुई"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन को रिकॉर्ड करने में गड़बड़ी आ रही है"</string> - <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"क्या रिकॉर्डिंग बंद करनी है?"</string> + <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"रिकॉर्ड करना बंद करना है?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"फ़िलहाल, पूरी स्क्रीन रिकॉर्ड की जा रही है"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"फ़िलहाल, <xliff:g id="APP_NAME">%1$s</xliff:g> की रिकॉर्डिंग की जा रही है"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"रिकॉर्ड करना बंद करें"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"स्क्रीन शेयर की जा रही है"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"क्या स्क्रीन शेयरिंग बंद करनी है?"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"स्क्रीन शेयर करना बंद करना है?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"फ़िलहाल, <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> पर पूरी स्क्रीन शेयर की जा रही है"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"फ़िलहाल, किसी ऐप्लिकेशन पर पूरी स्क्रीन शेयर की जा रही है"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"फ़िलहाल, <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> शेयर किया जा रहा है"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"फ़िलहाल, कोई ऐप्लिकेशन शेयर किया जा रहा है"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"शेयर करना बंद करें"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"स्क्रीन कास्ट की जा रही है"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"क्या कास्टिंग बंद करनी है?"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"कास्ट करना बंद करना है?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"फ़िलहाल, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर पूरी स्क्रीन कास्ट की जा रही है"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"फ़िलहाल, आस-पास मौजूद किसी डिवाइस पर पूरी स्क्रीन कास्ट की जा रही है"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"फ़िलहाल, <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> को <xliff:g id="DEVICE_NAME">%2$s</xliff:g> पर कास्ट किया जा रहा है"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"भेजें"</string> <string name="cancel" msgid="1089011503403416730">"रद्द करें"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ऐप्लिकेशन का लोगो"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"पुष्टि करें"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"फिर से कोशिश करें"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"पुष्टि की प्रक्रिया रद्द करने के लिए टैप करें"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नया डिवाइस जोड़ने के लिए क्लिक करें"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट नहीं किया जा सका"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"प्रीसेट"</string> - <string name="live_caption_title" msgid="8916875614623730005">"लाइव कैप्शन"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइव कैप्शन"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको माइक्रोफ़ोन का ऐक्सेस अनब्लॉक करना है?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको कैमरे का ऐक्सेस अनब्लॉक करना है?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग"</string> <string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद है"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"सेट अप करें"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"सेटिंग में जाकर मैनेज करें"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{कोई मोड चालू नहीं है}=1{{mode} चालू है}one{# मोड चालू है}other{# मोड चालू हैं}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"आपको अलार्म, रिमाइंडर, इवेंट और चुनिंदा कॉल करने वालों के अलावा किसी और तरह से (आवाज़ करके और थरथरा कर ) परेशान नहीं किया जाएगा. आप फिर भी संगीत, वीडियो और गेम सहित अपना चुना हुआ सब कुछ सुन सकते हैं."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"आपको अलार्म छोड़कर दूसरी आवाज़ों और कंपनों से परेशान नहीं किया जाएगा. आपको अब भी संगीत, वीडियो और गेम सहित वह सब कुछ सुनाई देगा जो आपने चलाने के लिए चुना है."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"अपनी पसंद के मुताबिक बनाएं"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • धीरे चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीन पर विजेट"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट, लॉक स्क्रीन में जोड़े गए"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"पसंद के मुताबिक बनाएं"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारिज करें"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास आपकी स्क्रीन पर दिख रही जानकारी या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. जैसे, पासवर्ड, पेमेंट के तरीके की जानकारी, फ़ोटो, मैसेज, और डिवाइस पर चल रहा ऑडियो."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"क्या मीडिया रिकॉर्ड या कास्ट करना है?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रिकॉर्ड या कास्ट करते समय, इस सुविधा को उपलब्ध कराने वाली सेवा के पास आपकी स्क्रीन पर दिख रही जानकारी या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. जैसे, पासवर्ड, पेमेंट के तरीके की जानकारी, फ़ोटो, मैसेज, और डिवाइस पर चल रहा ऑडियो."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"पूरी स्क्रीन"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"सिर्फ़ एक ऐप्लिकेशन"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"क्या <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> का इस्तेमाल करके रिकॉर्ड या कास्ट करना है?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"किसी ऐप्लिकेशन को शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रहे कॉन्टेंट या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"शुरू करें"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"क्या आपको <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर अपनी स्क्रीन शेयर करनी है?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक ऐप्लिकेशन शेयर करें"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरी स्क्रीन शेयर करें"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"जब पूरी स्क्रीन शेयर की जाती है, तो आपकी स्क्रीन पर दिख रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"जब कोई ऐप्लिकेशन शेयर किया जाता है, तो उस ऐप्लिकेशन में दिख रहा या चलाया जा रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेयर करें"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ने इस विकल्प को बंद कर दिया है"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"क्या कास्टिंग शुरू करनी है?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"कास्ट करते समय, Android के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"जब किसी ऐप्लिकेशन को कास्ट किया जाता है, तब उस पर दिख रहे कॉन्टेंट या चल रहे हर मीडिया का ऐक्सेस Android के पास होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर आपको सावधानी बरतनी चाहिए."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"कास्ट करें"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"क्या स्क्रीन को कास्ट करना है?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"एक ऐप्लिकेशन को कास्ट करें"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"पूरी स्क्रीन को कास्ट करें"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"पूरी स्क्रीन को कास्ट करने के दौरान, उस पर दिख रहा कॉन्टेंट दूसरी स्क्रीन पर भी दिखता है. इसलिए, कास्ट करते समय पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"किसी ऐप्लिकेशन को कास्ट करने के दौरान, उस पर दिख रहा कॉन्टेंट या चल रहा मीडिया दूसरी स्क्रीन पर भी दिखता है. इसलिए, कास्ट करते समय पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"स्क्रीन कास्ट करें"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"क्या मीडिया शेयर करना है?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"शेयर, रिकॉर्ड या कास्ट करते समय, Android के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"किसी ऐप्लिकेशन को शेयर, रिकॉर्ड या कास्ट करते समय, Android के पास उस ऐप्लिकेशन पर दिख रहे कॉन्टेंट या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"शुरू करें"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"आगे बढ़ें"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ऐप्लिकेशन स्विच करते समय शेयर करने की प्रोसेस रुक जाती है"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"इसके बजाय, यह ऐप्लिकेशन शेयर करें"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"वापस जाएं"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"सुलभता"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"कीबोर्ड शॉर्टकट"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"सर्च शॉर्टकट"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"खोज का कोई नतीजा नहीं मिला"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"छोटा करने का आइकॉन"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"बड़ा करने का आइकॉन"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"या"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम स्क्रीन पर जाने का जेस्चर"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ऐक्शन बटन"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"हो गया"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"बहुत बढ़िया!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"वापस जाएं"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"टचपैड पर तीन उंगलियों को दाईं और बाईं तरफ़ ले जाया जा रहा है"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"डिवाइस की स्क्रीन पर, पिछले पेज पर जाने के लिए हाथ के जेस्चर का ऐनिमेशन दिख रहा है"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"वापस जाने के लिए, टचपैड पर कहीं भी तीन उंगलियों से दाईं या बाईं ओर स्वाइप करें.\n\nइसके अलावा, ऐसा करने के लिए Action + ESC बटन का भी इस्तेमाल किया जा सकता है."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"बहुत बढ़िया!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"अब आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके, पिछली स्क्रीन पर वापस कैसे जाएं."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होम स्क्रीन पर जाएं"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"किसी भी समय फ़ोन की होम स्क्रीन पर जाने के लिए, तीन उंगलियों से फ़ोन पर सबसे नीचे से ऊपर की ओर स्वाइप करें."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"बढ़िया!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"आपने जान लिया कि हाथ का जेस्चर इस्तेमाल करके, होम स्क्रीन पर कैसे जाएं."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"ऐक्शन बटन"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"अपने ऐप्लिकेशन ऐक्सेस करने के लिए, कीबोर्ड पर ऐक्शन बटन दबाएं."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"बधाई हो!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"आपने ऐक्शन बटन का जेस्चर इस्तेमाल करने की प्रोसेस पूरी कर ली है.\n\nऐक्शन बटन और / को साथ में दबाने पर, आपके पास उपलब्ध सभी शॉर्टकट दिखते हैं."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड की बैकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d में से %1$d लेवल"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कंट्रोल"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"होम पर जाने के लिए, अपने डिवाइस के टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"हाल ही में इस्तेमाल हुए ऐप देखने के लिए, टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करके दबाकर रखें"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"सभी ऐप्लिकेशन देखने के लिए, कीबोर्ड पर ऐक्शन बटन दबाएं"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"जानकारी छिपाने के लिए सूचना में बदलाव किया गया"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"देखने के लिए डिवाइस अनलॉक करें"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"वापस जाने के लिए, अपने डिवाइस के टचपैड का इस्तेमाल करें"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"तीन उंगलियों से बाईं या दाईं ओर स्वाइप करें. जेस्चर के बारे में ज़्यादा जानने के लिए टैप करें."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"होम पर जाने के लिए, अपने डिवाइस के टचपैड का इस्तेमाल करें"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"तीन उंगलियों से ऊपर की ओर स्वाइप करें और दबाकर रखें. जेस्चर की ज़्यादा जानकारी पाने के लिए टैप करें."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"सभी ऐप्लिकेशन देखने के लिए, कीबोर्ड का इस्तेमाल करें"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"किसी भी समय ऐक्शन बटन दबाएं. हाथ के जेस्चर के बारे में ज़्यादा जानने के लिए टैप करें."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा, अब ब्राइटनेस बार का हिस्सा है"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"अब स्क्रीन के सबसे ऊपरी हिस्से से, स्क्रीन की रोशनी सामान्य लेवल से और कम की जा सकती है.\n\nयह सुविधा, अंधेरे वाली जगह पर बेहतर तरीके से काम करती है."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा का शॉर्टकट हटाएं"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा का शॉर्टकट हटा दिया गया. स्क्रीन की रोशनी कम करने के लिए, ब्राइटनेस बार का इस्तेमाल करें."</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 1d5051c3d5d1..75ffae2e79fd 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Snimač zaslona"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Želite li pokrenuti snimanje?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Dok snimate, Android ima pristup svemu što je vidljivo na zaslonu ili se reproducira na uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Dok snimate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Pokreni snimanje"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimanje zvuka"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk na uređaju"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk s vašeg uređaja, poput glazbe, poziva i melodija zvona"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošalji"</string> <string name="cancel" msgid="1089011503403416730">"Odustani"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotip aplikacije"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdi"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Pokušaj ponovo"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Dodirnite da biste otkazali autentifikaciju"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili novi uređaj"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje unaprijed definiranih postavki nije uspjelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Unaprijed definirana postavka"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Automatski titlovi"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatski titlovi"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite li deblokirati mikrofon uređaja?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite li deblokirati kameru uređaja?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite li deblokirati kameru i mikrofon uređaja?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Postavi"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte u postavkama"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih načina}=1{Aktivno: {mode}}one{# način je aktivan}few{# načina su aktivna}other{# načina je aktivno}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Neće vas ometati zvukovi i vibracije, osim alarma, podsjetnika, događaja i pozivatelja koje navedete. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Neće vas ometati zvukovi i vibracije, osim alarma. I dalje ćete čuti sve što želite reproducirati, uključujući glazbu, videozapise i igre."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prilagodi"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • sporo punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeti na zaključanom zaslonu"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> dodan je na zaključani zaslon"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Želite li pokrenuti snimanje ili emitiranje?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Cijeli zaslon"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikacija"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Dijeljenje ili snimanje aplikacije"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Želite li započeti snimanje ili emitiranje pomoću aplikacije <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kad dijelite, snimate ili emitirate, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što je vidljivo na zaslonu ili se reproducira na uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kad dijelite, snimate ili emitirate aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite li dijeliti zaslon s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeljenje jedne aplikacije"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeljenje cijelog zaslona"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli zaslon, sve na zaslonu bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeljenje zaslona"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> onemogućila je ovu opciju"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite li pokrenuti emitiranje?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kad emitirate, Android ima pristup svemu što je vidljivo na zaslonu ili se reproducira na uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kad emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Pokreni emitiranje"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Želite li emitirati zaslon?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Emitiranje jedne aplikacije"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Emitiranje cijelog zaslona"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kada emitirate cijeli zaslon, sve na zaslonu bit će vidljivo. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kada emitirate aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji bit će vidljivo. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Emitiranje zaslona"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Želite li pokrenuti dijeljenje?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kad dijelite, snimate ili emitirate, Android ima pristup svemu što je vidljivo na zaslonu ili se reproducira na uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kad dijelite, snimate ili emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke, fotografije te audio i videozapise."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Pokreni"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Dalje"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Dijeljenje pauza tijekom prebacivanja aplikacija"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Umjesto toga podijelite ovu aplikaciju"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Promjena računa"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pristupačnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tipkovni prečaci"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Prečaci za pretraživanje"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nema rezultata pretraživanja"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za sažimanje"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za otvaranje početnog zaslona"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka za radnju"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Sjajno!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Natrag"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Dodirna podloga prikazuje tri prsta koji se kreću udesno i ulijevo"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Na zaslonu uređaja prikazuje se animacija za pokret za povratak"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da biste se vratili natrag, s tri prsta prijeđite ulijevo ili udesno bilo gdje na dodirnoj podlozi.\n\nZa to možete upotrijebiti i tipku za radnju tipkovnog prečaca + ESC."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Sjajno!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvršili ste pokret za povratak."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Na početnu stranicu"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da biste u bilo kojem trenutku otvorili početni zaslon, trima prstima prijeđite prema gore od dna zaslona."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Odlično!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Izvršili ste pokret za otvaranje početnog zaslona."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka za radnju"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Da biste pristupili svojim aplikacijama, pritisnite tipku za radnje na tipkovnici."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Izvršili ste pokret tipke za radnju.\n\nRadnja + / prikazuje sve prečace koji su vam dostupni."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Razina %1$d od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Upravljanje uređajima"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Da biste se vratili na početni zaslon, prijeđite prema gore trima prstima na dodirnoj podlozi."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za prikaz nedavnih aplikacija prijeđite prema gore trima prstima i zadržite pritisak na dodirnoj podlozi"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za prikaz svojih svih aplikacija pritisnite tipku za radnju na tipkovnici"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redaktirano"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte za prikaz"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Upotrijebite dodirnu podlogu za povratak"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Prijeđite ulijevo ili udesno trima prstima. Dodirnite da biste naučili više pokreta."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Uz pomoć dodirne podloge vratite se na početni zaslon"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prijeđite prema gore trima prstima i zadržite pritisak. Dodirnite da biste naučili više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Upotrijebite tipkovnicu za prikaz svih aplikacija"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku za radnju u bilo kojem trenutku. Dodirnite da biste naučili više pokreta."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjenje sada je dio trake za svjetlinu"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Zaslon možete dodatno zatamniti daljnjim smanjivanjem razine svjetline na vrhu zaslona.\n\nTo najbolje funkcionira kada ste u tamnom okruženju."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečac za dodatno zatamnjenje"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Prečac za dodatno zatamnjenje je uklonjen. Da biste smanjili svjetlinu, upotrijebite regularnu traku za svjetlinu."</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 06040645840d..0c70afe8e4d3 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Képernyőrögzítő"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Elindítja a felvételt?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Rögzítés közben az Android a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Alkalmazás rögzítése közben az Android az adott alkalmazásban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Felvétel indítása"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Hang rögzítése"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Eszköz hangja"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Az eszköz által lejátszott hangok, például zeneszámok, hívások és csengőhangok"</string> @@ -127,7 +137,7 @@ <string name="screenrecord_save_error" msgid="5862648532560118815">"Hiba történt a képernyőrögzítés mentése során"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Hiba a képernyőrögzítés indításakor"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Leállítja a felvételt?"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Jelenleg a teljes képernyőről készít felvételt"</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Jelenleg a teljes képernyőről felvételt készít"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Jelenleg a következőről készít felvételt: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Felvétel leállítása"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Képernyő megosztása…"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Küldés"</string> <string name="cancel" msgid="1089011503403416730">"Mégse"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Alkalmazás emblémája"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Megerősítés"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Újrapróbálkozás"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Koppintson a hitelesítés visszavonásához"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kattintson új eszköz párosításához"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nem sikerült frissíteni a beállításkészletet"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Beállításkészlet"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Élő feliratozás"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Élő feliratozás"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Feloldja az eszköz mikrofonjának letiltását?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Feloldja az eszköz kamerájának letiltását?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Feloldja az eszköz kamerájának és mikrofonjának letiltását?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Beállítások"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Be"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Ki"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Beállítás"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"A Beállítások között kezelheti"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nincs aktív mód}=1{A(z) {mode} aktív}other{# mód aktív}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Az Ön által meghatározott ébresztéseken, emlékeztetőkön, eseményeken és hívókon kívül nem fogja Önt más hang vagy rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Az ébresztéseken kívül nem fogja Önt más hang és rezgés megzavarni. Továbbra is lesz hangjuk azoknak a tartalmaknak, amelyeket Ön elindít, például zenék, videók és játékok."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Személyre szabás"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lassú töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Modulok a lezárási képernyőn"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul felvéve a lezárási képernyőre"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Személyre szabás"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Elvetés"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"A(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, vagy amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés során. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, a fotók, az üzenetek és a lejátszott audiotartalmak."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Biztosan elkezdi a rögzítést vagy az átküldést?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"A funkciót biztosító szolgáltatás hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, illetve amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés közben. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, a fotók, az üzenetek és a lejátszott audiotartalmak."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Teljes képernyő"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Egyetlen alkalmazás"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Alkalmazás megosztása vagy rögzítése"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Elkezdi a rögzítést vagy az átküldést a következővel: <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Amikor Ön megosztást, rögzítést vagy átküldést végez, a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Amikor Ön megoszt, rögzít vagy átküld egy alkalmazást, a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Indítás"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Megosztja a képernyőjét a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkalmazással?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Egyetlen alkalmazás megosztása"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"A teljes képernyő megosztása"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"A teljes képernyő megosztása esetén a képernyő teljes tartalma látható lesz a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Alkalmazás megosztása közben az adott appban megjelenített vagy lejátszott minden tartalom látható a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Képernyő megosztása"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> letiltotta ezt a beállítást"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Elindítja az átküldést?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Amikor Ön átküldést végez, az Android a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Alkalmazás átküldése közben az Android az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Az átküldés indítása"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Átküldi a képernyőt?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Egyetlen app átküldése"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Teljes képernyő átküldése"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"A teljes képernyő átküldése esetén a képernyő teljes tartalma látható. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Alkalmazás átküldése közben az adott appban megjelenített vagy lejátszott minden tartalom látható. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Képernyőtartalom átküldése"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Megkezdi a megosztást?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Amikor Ön megosztást, rögzítést vagy átküldést végez, az Android a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Amikor Ön megoszt, rögzít vagy átküld egy alkalmazást, az Android az adott alkalmazásban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Indítás"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Következő"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"A megosztás szünetel alkalmazásváltáskor"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Inkább ennek az appnak a megosztása"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Visszaváltás"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Kisegítő lehetőségek"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Billentyűparancsok"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Billentyűparancsok keresése"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nincsenek keresési találatok"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Összecsukás ikon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kibontás ikon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vagy"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Kezdőképernyő kézmozdulat"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Műveletbillentyű"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kész"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kiváló!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Vissza"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"A visszalépéshez csúsztasson három ujjal balra vagy a jobbra az érintőpadon.\n\nEnnek végrehajtásához használhatja az Action + Esc billentyűparancsot is."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ugrás a főoldalra"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ha bármikor vissza szeretne térni a kezdőképernyőre, csúsztassa gyorsan felfelé három ujját a képernyő aljáról."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Három, jobbra és balra mozgó ujjat ábrázoló érintőpad"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"A Vissza kézmozdulat animációját megjelenítő eszközképernyő"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"A billentyűzet háttérvilágítása"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Fényerő: %2$d/%1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Otthon vezérlése"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"A kezdőképernyőre való ugráshoz csúsztasson felfelé három ujjal az érintőpadon."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"A legutóbbi appokért csúsztasson lefelé három ujjal az érintőpadon, és tartsa lenyomva ujjait."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Az összes alkalmazás megtekintéséhez nyomja meg a billentyűzet műveletbillentyűjét."</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Törölve"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Oldja fel a megtekintéshez"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"A visszalépéshez használja az érintőpadot"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Csúsztatasson gyorsan három ujjal balra vagy jobbra. Koppintson a további kézmozdulatokért."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"A kezdőképernyő megnyitásához használja az érintőpadot"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Gyúsztason felfelé három ujjal, és tartsa lenyomva az ujjait. Koppintson a további kézmozdulatokért."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"A billentyűzet használatával valamennyi alkalmazás megtekinthető"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"A műveletbillentyű bármikor használható. Koppintson a további kézmozdulatokért."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Az extrasötét funkció mostantól része a fényerő-beállítási sávnak"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"A képernyő tetején mostantól extrasötétre állíthatja a képernyőt, amivel a korábbinál még jobban csökkentheti a fényerőt.\n\nA funkció sötét környezetben használható a legjobban."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Az extrasötét funkció gyorsparancsának eltávolítása"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Eltávolította az extrasötét funkció gyorsparancsát. A fényerő csökkentéséhez használja a fényerő-beállítási sávot."</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 6f32125456b0..e9004032bc28 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Էկրանի տեսագրում"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Սկսե՞լ տեսագրումը"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Երբ դուք տեսագրում եք էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին և նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Երբ դուք տեսագրում եք որևէ հավելվածի էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Սկսել տեսագրումը"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Ձայնագրել"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Սարքի ձայները"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Ձեր սարքի ձայները, օրինակ՝ երաժշտությունը, զանգերն ու զանգերանգները"</string> @@ -126,9 +136,9 @@ <string name="screenrecord_save_text" msgid="3008973099800840163">"Հպեք՝ դիտելու համար"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"Չհաջողվեց պահել էկրանի տեսագրությունը"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Չհաջողվեց սկսել տեսագրումը"</string> - <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Կանգնեցնե՞լ ձայնագրումը"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Դուք ներկայումս ձայնագրում եք ձեր ամբողջ էկրանը"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Դուք ներկայումս ձայնագրում եք <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը"</string> + <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Կանգնեցնե՞լ տեսագրումը"</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Դուք ներկայումս տեսագրում եք ձեր ամբողջ էկրանը"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Դուք ներկայումս տեսագրում եք <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Կանգնեցնել տեսագրումը"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Միացված է էկրանի ցուցադրումը"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Դադարեցնե՞լ էկրանի ցուցադրումը"</string> @@ -145,7 +155,7 @@ <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Դուք ներկայումս հեռարձակում եք <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> հավելվածը մոտակա սարքին"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Դուք ներկայումս հեռարձակում եք <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքին"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Դուք ներկայումս հեռարձակում եք մոտակա սարքին"</string> - <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Դադարեցնել հեռարձակումը"</string> + <string name="cast_to_other_device_stop_dialog_button" msgid="6420183747435521834">"Կանգնեցնել հեռարձակումը"</string> <string name="close_dialog_button" msgid="4749497706540104133">"Փակել"</string> <string name="issuerecord_title" msgid="286627115110121849">"Խնդիրների տեսագրիչ"</string> <string name="issuerecord_background_processing_label" msgid="1666840264959336876">"Մշակում ենք տեսագրությունը"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Ուղարկել"</string> <string name="cancel" msgid="1089011503403416730">"Չեղարկել"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Հավելվածի լոգո"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Հաստատել"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Նորից փորձել"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Հպեք՝ նույնականացումը չեղարկելու համար"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Սեղմեք՝ նոր սարք զուգակցելու համար"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Չհաջողվեց թարմացնել կարգավորումների հավաքածուն"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Կարգավորումների հավաքածու"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Կենդանի ենթագրեր"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Կենդանի ենթագրեր"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Արգելահանե՞լ սարքի խոսափողը"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Արգելահանե՞լ սարքի տեսախցիկը"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Արգելահանե՞լ սարքի տեսախցիկը և խոսափողը"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Կարգավորումներ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Անջատված է"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Կարգավորել"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Կառավարել կարգավորումներում"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ակտիվ ռեժիմներ չկան}=1{{mode} ռեժիմ ակտիվ է}one{# ռեժիմ ակտիվ է}other{# ռեժիմ ակտիվ է}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ձայները և թրթռոցները չեն անհանգստացնի ձեզ, բացի ձեր կողմից նշված զարթուցիչները, հիշեցումները, միջոցառումների ծանուցումները և զանգերը։ Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ձայները և թրթռոցները, բացի զարթուցիչներից, չեն անհանգստացնի ձեզ: Դուք կլսեք ձեր ընտրածի նվագարկումը, այդ թվում՝ երաժշտություն, տեսանյութեր և խաղեր:"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Հարմարեցնել"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Դանդաղ լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Վիջեթներ կողպէկրանին"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"«<xliff:g id="WIDGET_NAME">%1$s</xliff:g>» վիջեթն ավելացվեց կողպէկրանին"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Անհատականացնել"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Փակել"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Տեսագրման և հեռարձակման ընթացքում <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Սկսե՞լ տեսագրումը կամ հեռարձակումը"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Տեսագրման և հեռարձակման ընթացքում ծառայությունների մատակարարին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Ամբողջ էկրանը"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Մեկ հավելված"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Հավելվածի էկրանի ցուցադրում կամ տեսագրում"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Սկսե՞լ տեսագրումը կամ հեռարձակումը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին և նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է լինում այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Սկսել"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ցուցադրե՞լ ձեր էկրանը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ցուցադրել մեկ հավելված"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ցուցադրել ամբողջ էկրանը"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Երբ ցուցադրում եք ամբողջ էկրանը, տեսանելի կլինի այն ամենը, ինչ ձեր էկրանին տեսանելի է <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Երբ դուք որևէ հավելված եք հեռարձակում, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին տեսանելի կլինի այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ցուցադրել էկրանը"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ն անջատել է այս ընտրանքը"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Սկսե՞լ հեռարձակումը"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Երբ դուք հեռարձակում եք էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին կամ նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Երբ դուք տեսագրում եք որևէ հավելվածի էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Սկսել հեռարձակումը"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Հեռարձակե՞լ ձեր էկրանը"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Հեռարձակել մեկ հավելված"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Հեռարձակել ամբողջ էկրանը"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Երբ հեռարձակում եք ամբողջ էկրանը, տեսանելի կլինի այն ամենը, ինչ ձեր էկրանին է։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Երբ դուք որևէ հավելված եք հեռարձակում, տեսանելի կլինի այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Հեռարձակել էկրանը"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Սկսե՞լ էկրանի ցուցադրումը"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին և նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ ցուցադրվում է կամ նվագարկվում այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Սկսել"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Առաջ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Երբ անցում եք կատարում մեկ այլ հավելվածի, ընթացիկ հավելվածի համատեղ օգտագործումը դադարեցվում է"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Փոխարենը կիսվել այս հավելվածով"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Վերադառնալ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Հատուկ գործառույթներ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Ստեղնային դյուրանցումներ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Դյուրանցումների որոնում"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Որոնման արդյունքներ չկան"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ծալել պատկերակը"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ծավալել պատկերակը"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"կամ"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Հիմնական էկրան անցնելու ժեստ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Գործողության ստեղն"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Պատրաստ է"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Կեցցե՛ք"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Հետ գնալ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Երեք մատները աջ ու ձախ են շարժվում հպահարթակի վրա"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Սարքի էկրանին ցուցադրվում է շարժանկար՝ հետ գնալու ժեստի համար"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Հետ գնալու համար հպահարթակի վրա երեք մատով սահեցրեք ձախ կամ աջ։\n\nԻնչպես նաև կարող եք օգտագործել ստեղնային դյուրանցման գործողությունը + Esc։"</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Կեցցե՛ք"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Դուք սովորեցիք հետ գնալու ժեստը։"</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Անցում հիմնական էկրան"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Հիմնական էկրան վերադառնալու համար երեք մատը էկրանի ներքևից սահեցրեք վերև։"</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Գերազանց է"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։"</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Գործողության ստեղն"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Բոլոր հավելվածներն օգտագործելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Շնորհավո՛ր"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Դուք սովորեցիք գործողության ստեղնի ժեստը։\n\nԳործողություն + / ժեստը ցույց է տալիս ձեզ հասանելի բոլոր դյուրանցումները։"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d՝ %2$d-ից"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Հիմնական էկրան անցնելու համար հպահարթակի վրա երեք մատը սահեցրեք ձախ կամ աջ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Վերջերս օգտագործված հավելվածները դիտելու համար երեք մատը սահեցրեք վերև և սեղմած պահեք"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Բոլոր հավելվածները դիտելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Կոդավորված"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ապակողպել դիտելու համար"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Օգտագործեք ձեր հպահարթակը՝ վերադառնալու համար"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Երեք մատը սահեցրեք ձախ կամ աջ։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Օգտագործեք ձեր հպահարթակը՝ հիմնական էկրան անցնելու համար"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Երեք մատը սահեցրեք վերև և սեղմած պահեք։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Օգտագործեք ձեր ստեղնաշարը՝ բոլոր հավելվածները դիտելու համար"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ցանկացած ժամանակ սեղմեք գործողության ստեղնը։ Հպեք՝ ավելի շատ ժեստերի ծանոթանալու համար։"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Հավելյալ խամրեցումն այժմ պայծառության գոտում է"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Էկրանը հավելյալ խամրեցնելու համար բացեք կարգավորումները էկրանի վերևի մասից։\n\nԽորհուրդ ենք տալիս օգտագործել այս գործառույթը, երբ շուրջը մութ է։"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Հեռացնել հավելյալ խամրեցման դյուրանցումը"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Հավելյալ խամրեցման դյուրանցումը հեռացվեց։ Պայծառության մակարդակը նվազեցնելու համար օգտագործեք պայծառության գոտին։"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 873372b1e44c..0b8499098865 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Perekam Layar"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Mulai Merekam?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Saat Anda merekam, Android akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Saat Anda merekam aplikasi, Android akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Mulai merekam"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Rekam audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio perangkat"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Suara dari perangkat Anda, seperti musik, panggilan, dan nada dering"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Kirim"</string> <string name="cancel" msgid="1089011503403416730">"Batal"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo aplikasi"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Konfirmasi"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Coba lagi"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ketuk untuk membatalkan autentikasi"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menyambungkan perangkat baru"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat memperbarui preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Teks Otomatis"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Teks Otomatis"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Berhenti memblokir mikrofon perangkat?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Berhenti memblokir kamera perangkat?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Berhenti memblokir kamera dan mikrofon perangkat?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setelan"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Nonaktif"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Siapkan"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Kelola di setelan"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Tidak ada mode yang aktif}=1{{mode} aktif}other{# mode aktif}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm, pengingat, acara, dan penelepon yang Anda tentukan. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Anda tidak akan terganggu oleh suara dan getaran, kecuali dari alarm. Anda akan tetap mendengar apa pun yang telah dipilih untuk diputar, termasuk musik, video, dan game."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Sesuaikan"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget di layar kunci"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan ke layar kunci"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Tutup"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Mulai merekam atau melakukan transmisi?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Layanan yang menyediakan fungsi ini akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Seluruh layar"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Satu aplikasi"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Bagikan atau rekam aplikasi"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Mulai merekam atau mentransmisikan dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Jika Anda membagikan, merekam, atau mentransmisikan, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio dan video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Mulai"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bagikan layar dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bagikan satu aplikasi"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bagikan seluruh layar"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"JIka Anda membagikan seluruh layar, semua hal yang ada di layar Anda akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Jika Anda membagikan aplikasi, semua hal yang ditampilkan atau diputar di aplikasi tersebut akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bagikan layar"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah menonaktifkan opsi ini"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Mulai transmisi?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Jika Anda melakukan transmisi, Android akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Jika Anda mentransmisikan aplikasi, Android akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Mulai transmisi"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Transmisikan layar?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmisikan satu aplikasi"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmisikan seluruh layar"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"JIka Anda mentransmisikan seluruh layar, semua hal yang ada di layar Anda akan terlihat. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Jika Anda mentransmisikan aplikasi, semua hal yang ditampilkan atau diputar di aplikasi tersebut akan terlihat. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Layar Cast"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Mulai berbagi?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Jika Anda membagikan, merekam, atau mentransmisikan, Android akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, Android akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Mulai"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Berikutnya"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Berbagi akan dijeda saat Anda beralih aplikasi"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Bagikan aplikasi ini"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Beralih kembali"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Aksesibilitas"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Pintasan keyboard"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Pintasan penelusuran"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Tidak ada hasil penelusuran"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon ciutkan"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon luaskan"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestur layar utama"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tombol tindakan"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bagus!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Untuk kembali, geser ke kiri atau kanan menggunakan tiga jari di touchpad.\n\nAnda juga dapat menggunakan pintasan keyboard Action + ECS untuk melakukannya."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Buka layar utama"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Untuk membuka layar utama kapan saja, geser ke atas menggunakan tiga jari dari bawah layar Anda."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad menampilkan tiga jari yang bergerak ke kanan dan ke kiri"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Layar perangkat menampilkan animasi untuk gestur kembali"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Lampu latar keyboard"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tingkat %1$d dari %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrol Rumah"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Untuk membuka layar utama, geser ke atas menggunakan tiga jari di touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Untuk melihat aplikasi terkini, geser ke atas dan tahan menggunakan tiga jari di touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua aplikasi, tekan tombol tindakan di keyboard"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Disamarkan"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Buka kunci untuk melihat"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Gunakan touchpad untuk kembali"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Geser ke kiri atau kanan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Gunakan touchpad untuk membuka layar utama"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Geser ke atas dan tahan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan keyboard untuk melihat semua aplikasi"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan tombol tindakan kapan saja. Ketuk untuk mempelajari gestur lainnya."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra redup kini menjadi bagian dari panel kecerahan"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Anda kini dapat membuat layar menjadi ekstra redup dengan menurunkan tingkat kecerahan lebih banyak lagi dari bagian atas layar.\n\nFitur ini berfungsi optimal saat Anda berada di tempat yang gelap."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Hapus pintasan ekstra redup"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Pintasan ekstra redup dihapus. Untuk menurunkan kecerahan, gunakan panel kecerahan biasa."</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 50145b06a06e..606a64c4ebd1 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Skjáupptaka"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Hefja upptöku?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Þegar þú tekur upp hefur Android aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Þegar þú tekur upp forrit hefur Android aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Hefja upptöku"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Taka upp hljóð"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Hljóð tækis"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Hljóð úr tækinu á borð við tónlist, símtöl og hringitóna"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Senda"</string> <string name="cancel" msgid="1089011503403416730">"Hætta við"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Lógó forrits"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Staðfesta"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Reyna aftur"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ýttu til að hætta við auðkenningu"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Smelltu til að para nýtt tæki"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tókst ekki að uppfæra forstillingu"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forstilling"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Skjátextar í rauntíma"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Skjátextar í rauntíma"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Opna fyrir hljóðnema tækisins?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Opna fyrir myndavél tækisins?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Opna fyrir myndavél og hljóðnema tækisins?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Stillingar"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Slökkt"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Setja upp"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Stjórna í stillingum"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Engar virkar stillingar}=1{{mode} er virk}one{# stilling er virk}other{# stillingar eru virkar}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara, áminningar, viðburði og símtöl frá þeim sem þú leyfir fyrirfram. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Þú verður ekki fyrir truflunum frá hljóðmerkjum og titringi, fyrir utan vekjara. Þú heyrir áfram í öllu sem þú velur að spila, svo sem tónlist, myndskeiðum og leikjum."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Sérsníða"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Hæg hleðsla • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Græjur á lásskjá"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Græjunni „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ var bætt við lásskjá"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sérsníða"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hunsa"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> mun hafa aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða vörpun er í gangi. Þar á meðal eru upplýsingar á borð við aðgangsorð, greiðsluupplýsingar, myndir, skilaboð og hljóð sem þú spilar."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Viltu hefja upptöku eða vörpun?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Þjónustan sem býður upp á þennan eiginleika fær aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða vörpun er í gangi, þar á meðal aðgangsorði, greiðsluupplýsingum, myndum, skilaboðum og hljóðefni sem þú spilar."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Allur skjárinn"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Eitt forrit"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Deila eða taka upp forrit"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Viltu hefja upptöku eða vörpun með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Þegar þú deilir, tekur upp eða varpar hefur<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Þegar þú deilir, tekur upp eða varpar forriti hefur <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Byrja"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deila skjánum með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deila einu forriti"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deila öllum skjánum"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Þegar þú deilir öllum skjánum verður allt á skjánum sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Þegar þú deilir forriti er allt sem sést eða er spilað í því forriti sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deila skjá"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> slökkti á þessum valkosti"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Byrja að varpa?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Þegar þú varpar hefur Android aðgang að öllu sem er sýnilegt á skjánum hjá þér eða spilast í tækinu þínu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Þegar þú varpar forriti hefur Android aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Byrja að varpa"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Varpa skjánum?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Varpa einu forriti"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Varpa öllum skjánum"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Þegar þú varpar öllum skjánum þá er allt á skjánum sýnilegt. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Þegar þú varpar forriti er allt sem sést eða er spilað í því forriti sýnilegt. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Senda út skjá"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Byrja að deila?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Þegar þú deilir, tekur upp eða varpar hefur Android aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Þegar þú deilir, tekur upp eða varpar forriti hefur Android aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Byrja"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Áfram"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Hlé er gert á samnýtingu þegar þú skiptir um forrit"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Deila frekar þessu forriti"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Skipta til baka"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Aðgengi"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Flýtilyklar"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Leitarflýtileiðir"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Engar leitarniðurstöður"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Minnka tákn"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Stækka tákn"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eða"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bending til að fara á upphafsskjá"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aðgerðalykill"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Lokið"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Vel gert!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Til baka"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Strjúktu til vinstri eða hægri með þremur fingrum hvar sem er á snertifletinum til að fara til baka.\n\nÞú getur einnig notað flýtileiðaraðgerðina + ESC til að gera þetta."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Heim"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Strjúktu upp frá neðri brún skjásins með þremur fingrum til að opna heimaskjáinn."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Snertiflötur sem sýnir þrjá fingur færast til hægri og vinstri"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skjár tækis sem sýnir hreyfimynd fyrir bendinguna „til baka“."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stig %1$d af %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Heimastýringar"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Strjúktu upp með þremur fingrum á snertifletinum til að fara á heimaskjá"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Strjúktu upp og haltu með þremur fingrum á snertifletinum til að sjá nýleg forrit"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ýttu á aðgerðalykilinn á lyklaborðinu til að sjá öll forritin þín"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Ritskoðað"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Taktu úr lás til að skoða"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Notaðu snertiflötinn til að fara til baka"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Strjúktu til vinstri eða hægri með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Notaðu snertiflötinn til að fara á heimaskjá"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Strjúktu upp og haltu með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Notaðu lyklaborðið til að sjá öll forrit"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ýttu hvenær sem er á aðgerðalykilinn. Ýttu til að læra fleiri bendingar."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Nú er stillingin „mjög dökkt“ hluti af birtustigsstikunni"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nú geturðu gert skjáinn mjög dökkan með því að lækka birtustigið enn frekar efst á skjánum.\n\nÞetta virkar best þegar umhverfi þitt er mjög dimmt."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjarlægja flýtilykil á mjög dökka stillingu"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Flýtilykill á mjög dökka stillingu fjarlægður. Notaðu hefðbundnu birtustigsstikuna til að lækka birtustigið."</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 502678eb3e47..8f88b053896e 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Registrazione dello schermo"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaborazione registrazione…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Iniziare a registrare?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Quando registri, Android ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Quando registri un\'app, Android ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Avvia registrazione"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Registra audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Suoni del dispositivo, come musica, chiamate e suonerie"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Invia"</string> <string name="cancel" msgid="1089011503403416730">"Annulla"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo dell\'app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Conferma"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Riprova"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tocca per annullare l\'autenticazione"</string> @@ -227,7 +235,7 @@ <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Configura lo Sblocco con il Volto"</string> <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Per riconfigurare lo Sblocco con il Volto, l\'attuale modello del volto verrà eliminato.\n\nDovrai riconfigurare questa funzionalità per usare il volto per sbloccare lo smartphone."</string> <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossibile configurare lo Sblocco con il Volto. Vai alle Impostazioni e riprova."</string> - <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte"</string> + <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte digitali"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Premi l\'icona Sblocca per continuare"</string> <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Volto non riconosciuto. Usa l\'impronta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> @@ -250,9 +258,7 @@ <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN attiva."</string> <string name="accessibility_battery_level" msgid="5143715405241138822">"Batteria: <xliff:g id="NUMBER">%d</xliff:g> percento."</string> <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Batteria rimanente: <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cento, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- String.format failed for translation --> - <!-- no translation found for accessibility_battery_level_charging (8892191177774027364) --> - <skip /> + <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batteria in carica, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string> <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Batteria a <xliff:g id="PERCENTAGE">%d</xliff:g> per cento; ricarica in pausa per proteggere la batteria."</string> <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Batteria a <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cento, <xliff:g id="TIME">%2$s</xliff:g>; ricarica in pausa per proteggere la batteria."</string> <string name="accessibility_overflow_action" msgid="8555835828182509104">"Visualizza tutte le notifiche"</string> @@ -298,7 +304,7 @@ <string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tocca per connettere o disconnettere un dispositivo"</string> <string name="pair_new_bluetooth_devices" msgid="4601767620843349645">"Accoppia nuovo dispositivo"</string> <string name="see_all_bluetooth_devices" msgid="1761596816620200433">"Visualizza tutti"</string> - <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa Bluetooth"</string> + <string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa il Bluetooth"</string> <string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Dispositivo connesso"</string> <string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Condivisione audio"</string> <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string> @@ -402,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fai clic per accoppiare un nuovo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossibile aggiornare preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Sottotitoli in tempo reale"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sottotitoli in tempo reale"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vuoi sbloccare il microfono del dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vuoi sbloccare la fotocamera del dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vuoi sbloccare la fotocamera e il microfono del dispositivo?"</string> @@ -477,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ricarica lenta • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget su schermata di blocco"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> aggiunto alla schermata di blocco"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizza"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chiudi"</string> @@ -530,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vuoi avviare la registrazione o la trasmissione?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Il servizio che offre questa funzione avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Schermo intero"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Una sola app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Condividi o registra un\'app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vuoi avviare la registrazione o la trasmissione con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando condividi, registri o trasmetti, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando condividi, registri o trasmetti un\'app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Inizia"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Condividere lo schermo con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Condividi un\'app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Condividi schermo intero"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando condividi lo schermo intero, tutto ciò che è nella schermata è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando condividi un\'app, tutto ciò che viene mostrato o riprodotto al suo interno è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Condividi schermo"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha disattivato questa opzione"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Iniziare a trasmettere?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando trasmetti, Android ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando trasmetti un\'app, Android ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Inizia a trasmettere"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Trasmettere lo schermo?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Trasmetti un\'app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Trasmetti schermo intero"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Quando trasmetti lo schermo intero, tutto ciò che è nella schermata è visibile. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Quando trasmetti un\'app, tutto ciò che viene mostrato o riprodotto al suo interno è visibile. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Trasmetti schermo"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Iniziare a condividere?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Quando condividi, registri o trasmetti, Android ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Quando condividi, registri o trasmetti un\'app, Android ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Inizia"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Avanti"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"La condivisione viene messa in pausa quando cambi app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Condividi invece questa app"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Torna indietro"</string> @@ -1375,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibilità"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Scorciatoie da tastiera"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Scorciatoie per la ricerca"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nessun risultato di ricerca"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona Comprimi"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona Espandi"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oppure"</string> @@ -1382,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto Home"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasto azione"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fine"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Ottimo lavoro"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Indietro"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Per tornare indietro, scorri verso sinistra o verso destra utilizzando tre dita in un punto qualsiasi del touchpad.\n\nPuoi usare anche la scorciatoia da tastiera Action + Esc per farlo."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Vai alla schermata Home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Per andare alla schermata Home, scorri verso l\'alto con tre dita dalla parte inferiore dello schermo."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad che mostra tre dita che si muovono verso destra e sinistra"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Schermata del dispositivo che mostra l\'animazione del gesto per tornare indietro"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Livello %1$d di %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlli della casa"</string> @@ -1399,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Per andare alla schermata Home, scorri verso l\'alto con tre dita sul touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Per visualizzare le app recenti, scorri verso l\'alto e tieni premuto con tre dita sul touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per visualizzare tutte le tue app, premi il tasto azione sulla tastiera"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Oscurata"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Sblocca per visualizzare"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa il touchpad per tornare indietro"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Scorri verso sinistra o destra con tre dita. Tocca per scoprire altri gesti."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa il touchpad per andare alla schermata Home"</string> @@ -1407,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Scorri verso l\'alto e tieni premuto con tre dita. Tocca per scoprire altri gesti."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa la tastiera per visualizzare tutte le app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Premi il tasto azione in qualsiasi momento. Tocca per scoprire altri gesti."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ora l\'attenuazione extra è nella barra della luminosità"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ora puoi usare l\'attenuazione extra per lo schermo abbassando il livello di luminosità ancora di più dalla parte superiore della schermata.\n\nQuesta funzionalità opera in modo ottimale quando ti trovi in un ambiente buio."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Rimuovi scorciatoia attenuazione extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Scorciatoia attenuazione extra rimossa. Per diminuire la luminosità, usa la normale barra della luminosità."</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 698d2add6044..8d9bf3454be0 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"מקליט המסך"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"להתחיל את ההקלטה?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"בזמן ההקלטה, תהיה ל-Android גישה לכל מה שמופיע במסך שלך או מופעל במכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"בזמן הקלטה של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"התחלת ההקלטה"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"הקלטת אודיו"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"אודיו מהמכשיר"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"צלילים מהמכשיר, כמו מוזיקה, שיחות ורינגטונים"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"שליחה"</string> <string name="cancel" msgid="1089011503403416730">"ביטול"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"לוגו של האפליקציה"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"אישור"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ניסיון נוסף"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"יש להקיש כדי לבטל את האימות"</string> @@ -217,17 +225,17 @@ <string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"לא עכשיו"</string> <string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"הפעולה הזו נדרשת כדי לשפר את האבטחה והביצועים"</string> <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"הגדרה חוזרת של \'ביטול הנעילה בטביעת אצבע\'"</string> - <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"ביטול הנעילה בטביעת אצבע"</string> + <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"פתיחה בטביעת אצבע"</string> <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"הגדרת \'ביטול הנעילה בטביעת אצבע\'"</string> <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"כדי להגדיר שוב את התכונה \'ביטול הנעילה בטביעת אצבע\', עליך למחוק את התבניות והמודלים הנוכחיים של טביעת האצבע.\n\nאחרי המחיקה יהיה צורך להגדיר שוב את \'ביטול הנעילה בטביעת אצבע\' כדי להשתמש בטביעת האצבע לביטול הנעילה של הטלפון ולאמת את זהותך."</string> <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"כדי להגדיר שוב את התכונה \'ביטול הנעילה בטביעת אצבע\', עליך למחוק את התבניות והמודל הנוכחיים של טביעת האצבע.\n\nאחרי המחיקה יהיה צורך להגדיר שוב את \'ביטול הנעילה בטביעת אצבע\' כדי להשתמש בטביעת האצבע לביטול הנעילה של הטלפון ולאמת את זהותך."</string> <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"לא ניתן להגדיר ביטול נעילה בטביעת אצבע. יש לעבור להגדרות כדי לנסות שוב."</string> <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"הגדרה חוזרת של \'פתיחה ע\"י זיהוי הפנים\'"</string> - <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"פתיחה ע\"י זיהוי הפנים"</string> + <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"פתיחה בזיהוי פנים"</string> <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"להגדרת התכונה \'פתיחה ע\"י זיהוי הפנים\'"</string> <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"כדי להגדיר שוב את התכונה \'פתיחה ע\"י זיהוי הפנים\', עליך למחוק את התבנית הנוכחית לזיהוי הפנים.\n\nיהיה צורך להגדיר את התכונה הזו שוב כדי להשתמש בזיהוי הפנים לביטול הנעילה של הטלפון."</string> <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"לא ניתן להגדיר פתיחה ע\"י זיהוי הפנים. צריך לעבור להגדרות כדי לנסות שוב."</string> - <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"יש לגעת בחיישן טביעות האצבע"</string> + <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"צריך לגעת בחיישן טביעות האצבע"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"להמשך יש ללחוץ על סמל ביטול הנעילה"</string> <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"הפנים לא זוהו. צריך להשתמש בטביעת אצבע במקום."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"צריך ללחוץ כדי להתאים מכשיר חדש"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"לא ניתן לעדכן את ההגדרה הקבועה מראש"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"הגדרה קבועה מראש"</string> - <string name="live_caption_title" msgid="8916875614623730005">"כתוביות מיידיות"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"כתוביות מיידיות"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"לבטל את חסימת המיקרופון של המכשיר?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"לבטל את חסימת המצלמה של המכשיר?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"לבטל את חסימת המצלמה והמיקרופון של המכשיר?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"הגדרות"</string> <string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string> <string name="zen_mode_off" msgid="1736604456618147306">"מצב מושבת"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"הגדרה"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"שינוי ב\'הגדרות\'"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{אין מצבים פעילים}=1{מצב פעיל אחד ({mode})}one{# מצבים פעילים}two{# מצבים פעילים}other{# מצבים פעילים}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות, תזכורות, אירועים ושיחות ממתקשרים מסוימים לבחירתך. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"התאמה אישית"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה איטית • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ווידג\'טים במסך הנעילה"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"הווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g> נוסף למסך הנעילה"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"התאמה אישית"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"סגירה"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"לאפליקציית <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> תהיה גישה לכל המידע הגלוי במסך שלך ולכל תוכן שמופעל במכשיר שלך בזמן הקלטה או הפעלת Cast. המידע הזה כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"להתחיל הקלטה או הפעלת Cast?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או הפעלת Cast – כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"כל המסך"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"אפליקציה אחת"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"שיתוף או הקלטה של אפליקציה"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"להתחיל להקליט או להפעיל Cast דרך <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"בזמן שיתוף, הקלטה או הפעלת Cast תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"בזמן שיתוף, הקלטה או הפעלת Cast של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"התחלה"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"לשתף את המסך שלך עם <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"שיתוף של אפליקציה אחת"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"שיתוף כל המסך"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"כשמשתפים את כל המסך, כל מה שמופיע בו יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"כשמשתפים אפליקציה, כל מה שרואים או מפעילים בה יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"שיתוף המסך"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> השביתה את האפשרות הזו"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"להפעיל Cast?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"בזמן הפעלת Cast, תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"בזמן Cast מאפליקציה, תהיה ל-Android גישה לכל מה שמופיע באפליקציה ולכל מדיה שפועלת בה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"הפעלת Cast"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"להפעיל Cast של המסך?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"הפעלת Cast של אפליקציה אחת"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"הפעלת Cast של כל המסך"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"כשמפעילים Cast של כל המסך, כל מה שמופיע בו יהיה גלוי לצופים. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"כשמפעילים Cast של כל אפליקציה, כל מה שמופיע או מופעל בה יהיה גלוי לצופים. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"הפעלת Cast של המסך"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"להתחיל את השיתוף?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"בזמן שיתוף, הקלטה או הפעלת Cast תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"בזמן שיתוף, הקלטה או הפעלת Cast של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"התחלה"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"הבא"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"השיתוף מושהה כשמחליפים אפליקציות"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"שיתוף של האפליקציה הזו במקום"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"חזרה למשימה הקודמת"</string> @@ -1368,7 +1380,7 @@ <string name="shortcut_helper_category_system_controls" msgid="3153344561395751020">"הגדרות המערכת"</string> <string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"אפליקציות מערכת"</string> <string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"ריבוי משימות"</string> - <string name="shortcutHelper_category_recent_apps" msgid="7918731953612377145">"אפליקציות אחרונות"</string> + <string name="shortcutHelper_category_recent_apps" msgid="7918731953612377145">"אפליקציות שהיו בשימוש לאחרונה"</string> <string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"מסך מפוצל"</string> <string name="shortcut_helper_category_input" msgid="8674018654124839566">"קלט"</string> <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"קיצורי דרך של אפליקציות"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"נגישות"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"מקשי קיצור"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"קיצורי דרך לחיפוש"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"אין תוצאות חיפוש"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"סמל הכיווץ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"סמל ההרחבה"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"או"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"תנועת חזרה למסך הבית"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"מקש הפעולה"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"מעולה!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות בכל מקום על לוח המגע.\n\nאפשר לבצע את הפעולה הזו גם באמצעות קיצור הדרך לפעולה + מקש ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"מעבר לדף הבית"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"כדי לעבור למסך הבית בכל שלב, צריך להחליק למעלה עם שלוש אצבעות מהחלק התחתון של המסך."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"לוח מגע שמראה שלוש אצבעות זזות ימינה ושמאלה"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"מסך מכשיר שמראה אנימציה לתנועה אחורה"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"רמה %1$d מתוך %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"שליטה במכשירים"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"כדי לעבור למסך הבית, מחליקים למעלה עם שלוש אצבעות על לוח המגע"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"כדי לראות את האפליקציות האחרונות, מחליקים למעלה עם שלוש אצבעות על לוח המגע ולוחצים לחיצה ארוכה"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"כדי לראות את כל האפליקציות, מקישים על מקש הפעולה במקלדת"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"מצונזר"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"צריך לבטל את הנעילה כדי לראות"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"איך להשתמש בלוח המגע כדי לחזור אחורה"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"מחליקים ימינה או שמאלה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"איך להשתמש בלוח המגע כדי לעבור למסך הבית"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"מחליקים למעלה ולוחצים לחיצה ארוכה עם שלוש אצבעות. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"איך להשתמש במקלדת כדי לראות את כל האפליקציות"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"בכל שלב אפשר ללחוץ על מקש הפעולה. ניתן להקיש כדי לקבל מידע נוסף על התנועות."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"התכונה \'מעומעם במיוחד\' נוספה לסרגל הבהירות"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"עכשיו אפשר להפוך את המסך למעומעם במיוחד באמצעות הפחתה נוספת של רמת הבהירות דרך החלק העליון במסך.\n\nהפעולה הזו עובדת הכי טוב בסביבה חשוכה."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"הסרה של קיצור הדרך לתכונה \'מעומעם במיוחד\'"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"קיצור הדרך לתכונה \'מעומעם במיוחד\' הוסר. כדי להפחית את הבהירות, אפשר להשתמש בסרגל הבהירות הרגיל."</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 7e09b94fec71..3c6baba7c78b 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"スクリーン レコーダー"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"録画を開始しますか?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"録画中は、表示や再生される内容に Android がアクセスできます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"アプリの録画中は、そのアプリで表示または再生される内容に Android がアクセスできます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"録画を開始"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"録音"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"デバイスの音声"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"デバイスからの音(音楽、通話、着信音など)"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"送信"</string> <string name="cancel" msgid="1089011503403416730">"キャンセル"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"アプリのロゴ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"再試行"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"タップすると認証をキャンセルします"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"クリックすると、新しいデバイスをペア設定できます"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"プリセットを更新できませんでした"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"プリセット"</string> - <string name="live_caption_title" msgid="8916875614623730005">"自動字幕起こし"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"自動字幕起こし"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"デバイスのマイクのブロックを解除しますか?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"デバイスのカメラのブロックを解除しますか?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"デバイスのカメラとマイクのブロックを解除しますか?"</string> @@ -475,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 低速充電中 • 完了まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ロック画面のウィジェット"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ウィジェットをロック画面に追加しました"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"カスタマイズ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"閉じる"</string> @@ -528,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> は、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"録画やキャストを開始しますか?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"この機能を提供するサービスは、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"画面全体"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"1 つのアプリ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"アプリの共有または録画"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> で録画やキャストを開始しますか?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"共有、録画、キャスト中は、画面に表示される内容やデバイスで再生される内容に <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"アプリの共有、録画、キャスト中は、そのアプリで表示または再生される内容に <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> と画面を共有しますか?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"1 つのアプリを共有"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"画面全体を共有"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"画面全体を共有すると、画面に表示される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"アプリを共有すると、そのアプリで表示または再生される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"画面を共有"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> がこのオプションを無効にしています"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"キャストを開始しますか?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"キャスト中は、画面に表示される内容やデバイスで再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"アプリのキャスト中は、そのアプリで表示または再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"キャストを開始"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"画面をキャストしますか?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"1 つのアプリをキャスト"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"画面全体をキャスト"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"画面全体をキャストすると、画面に表示される内容がすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"アプリをキャストすると、そのアプリで表示または再生される内容がすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"画面のキャスト"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"共有を開始しますか?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"共有、録画、キャスト中は、画面に表示される内容やデバイスで再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"アプリの共有、録画、キャスト中は、そのアプリで表示または再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"開始"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"次へ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"アプリを切り替えるときに共有を一時停止します"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"代わりにこのアプリを共有する"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"切り替える"</string> @@ -1373,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ユーザー補助"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"キーボード ショートカット"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"検索ショートカット"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"検索結果がありません"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"閉じるアイコン"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"開くアイコン"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"または"</string> @@ -1380,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"「ホーム」ジェスチャー"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"アクションキー"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完了"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"よくできました。"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"戻る"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"タッチパッドで 3 本の指を左右に動かしている様子"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"デバイスの画面で「戻る」ジェスチャーのアニメーションが表示されている様子"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"戻るには、3 本の指でタッチパッドを左右にスワイプします。\n\nキーボード ショートカットのアクション + ESC キーを使用して、この操作を行うこともできます。"</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"お疲れさまでした。"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"「戻る」操作を学習しました。"</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ホームに移動"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"3 本の指で画面を下から上にスワイプすると、ホーム画面にいつでも移動できます。"</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"お疲れさまでした。"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"「ホームに移動」操作を学習しました。"</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"アクションキー"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"アプリにアクセスするには、キーボードのアクションキーを押します。"</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"お疲れさまでした。"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"アクションキー操作を学習しました。\n\nアクションキーと + キーを同時に押すと、利用可能なショートカットがすべて表示されます。"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"レベル %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ホーム コントロール"</string> @@ -1397,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ホームに移動するには、3 本の指でタッチパッドを上にスワイプします"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"最近使ったアプリを表示するには、3 本の指でタッチパッドを上にスワイプして長押しします"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"すべてのアプリを表示するには、キーボードのアクションキーを押してください"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"削除済み"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"表示するにはロックを解除してください"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"タッチパッドを使用して、前の画面に戻る"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"3 本の指で左または右にスワイプします。ジェスチャーの詳細を確認するにはタップしてください。"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"タッチパッドを使用して、ホームに移動する"</string> @@ -1405,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"3 本の指で上にスワイプして長押しします。ジェスチャーの詳細を確認するにはタップしてください。"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"キーボードを使用して、すべてのアプリを表示する"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"アクションキーを押せばいつでも機能します。ジェスチャーの詳細を確認するにはタップしてください。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"「さらに輝度を下げる」機能が明るさのバーの追加されました"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"画面の上部で明るさを大幅に低く設定することで、画面の輝度をさらに下げられるようになりました。\n\nこの設定は暗い場所での操作に最適です。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"「さらに輝度を下げる」のショートカットを削除する"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"「さらに輝度を下げる」のショートカットを削除しました。明るさを下げるには、通常の明るさのバーを使用してください。"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 4d0e90cd8079..d9cb740ec1c6 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ეკრანის ჩამწერი"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"დაიწყოს ჩაწერა?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"სანამ აპის ჩაწერას ახორციელებთ, Android-ს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენი მოწყობილობის მეშვეობით. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"სანამ აპს იწერთ, Android-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან რასაც უკრავთ აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ჩაწერის დაწყება"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"აუდიოს ჩაწერა"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"მოწყობილობის აუდიო"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ხმა თქვენი მოწყობილობიდან, როგორიც არის მუსიკა, საუბარი და ზარები"</string> @@ -132,7 +142,7 @@ <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"ჩაწერის შეწყვეტა"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"მიმდინარეობს ეკრანის გაზიარება"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"გსურთ ეკრანის გაზიარების შეწყვეტა?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"თქვენ ამჟამად უზიარებთ თქვენს მთლიან ეკრანს<xliff:g id="HOST_APP_NAME">%1$s</xliff:g>-ს"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"თქვენ ამჟამად უზიარებთ თქვენს მთლიან ეკრანს <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>-ს"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"თქვენ ამჟამად უზიარებთ თქვენს მთლიან ეკრანს აპს"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"თქვენ ამჟამად აზიარებთ <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>-ს"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"თქვენ ამჟამად აზიარებთ აპს"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"გაგზავნა"</string> <string name="cancel" msgid="1089011503403416730">"გაუქმება"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"აპის ლოგო"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"დადასტურება"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ხელახლა ცდა"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"შეეხეთ ავტორიზაციის გასაუქმებლად"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"დააწკაპუნეთ ახალი მოწყობილობის დასაწყვილებლად"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"წინასწარ დაყენებული პარამეტრების განახლება ვერ მოხერხდა"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"წინასწარ დაყენებული"</string> - <string name="live_caption_title" msgid="8916875614623730005">"ავტოსუბტიტრები"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ავტოსუბტიტრები"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"გსურთ მოწყობილობის მიკროფონის განბლოკვა?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"გსურთ მოწყობილობის კამერის განბლოკვა?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"გსურთ მოწყობილობის კამერის და მიკროფონის განბლოკვა?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"პარამეტრები"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string> <string name="zen_mode_off" msgid="1736604456618147306">"გამორთული"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"დაყენება"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"პარამეტრებში მართვა"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{აქტიური რეჟიმები არ მოიძებნა}=1{{mode} აქტიურია}other{აქტიურია # რეჟიმი}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"თქვენ მიერ მითითებული მაღვიძარების, შეხსენებების, მოვლენებისა და ზარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"მაღვიძარების გარდა, არავითარი ხმა და ვიბრაცია არ შეგაწუხებთ. თქვენ მაინც შეძლებთ სასურველი კონტენტის, მაგალითად, მუსიკის, ვიდეოებისა და თამაშების აუდიოს მოსმენა."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"მორგება"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ნელა იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ვიჯეტები ჩაკეტილ ეკრანზე"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი დაემატა ჩაკეტილ ეკრანს"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"მორგება"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"უარყოფა"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"დაიწყოს ჩაწერა ან ტრანსლირება?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ამ ფუნქციის მომწოდებელ სერვისს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"მთელი ეკრანი"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ერთი აპი"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"გააზიარეთ ან ჩაწერეთ აპი"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"დაიწყოს ჩაწერა ან ტრანსლირება <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ით?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"გაზიარების, ჩაწერის ან ტრანსლირების დროს, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან იკვრება აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"დაწყება"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"გსურთ თქვენი ეკრანის <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-თან გაზიარება?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ერთი აპის გაზიარება"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"მთლიანი ეკრანის გაზიარება"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"მთლიანი ეკრანის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც თქვენს ეკრანზეა. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"აპის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც ჩანს ან უკრავს ამ აპში. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ეკრანის გაზიარება"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>-მა გათიშა ეს ვარიანტი"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"გსურთ ტრანსლირების დაწყება?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"როდესაც თქვენ ტრანსლირებთ, ამ აპს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"როდესაც აპს ტრანსლირებთ, Android-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან იკვრება აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ტრანსლირების დაწყება"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"გსურთ თქვენი ეკრანის ტრანსლირება?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ერთი აპის ტრანსლირება"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"მთლიანი ეკრანის ტრანსლირება"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"თქვენი მთლიანი ეკრანის ტრანსლირების დროს, რაც თქვენს ეკრანზეა ყველაფერი ჩანს. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"აპის ტრანსლირების დროს ყველაფერი ჩანს, რაც იკვრება ან გამოსახულია აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"ეკრანის ტრანსლირება"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"გსურთ გაზიარების დაწყება?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"გაზიარებისას, ჩაწერისას ან ტრანსლირებისას, Android-ს წვდომა აქვს ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას, Android-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან იკვრება აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"დაწყება"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"შემდეგი"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"აპების გადართვისას გაზიარება პაუზდება"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"სანაცვლოდ ამ აპის გაზიარება"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"უკან გადართვა"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"მისაწვდომობა"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"კლავიატურის მალსახმობები"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ძიების მალსახმობები"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ძიების შედეგები არ არის"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ხატულის ჩაკეცვა"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ხატულის გაფართოება"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ან"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"მთავარ ეკრანზე გადასვლის ჟესტი"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"მოქმედების კლავიში"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"მზადაა"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"შესანიშნავია!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"უკან დაბრუნება"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"სენსორული პანელი, რომელიც აჩვენებს მარჯვენა და მარცხენა მიმართულებით მოძრავ სამ თითს"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"მოწყობილობის ეკრანი, რომელიც აჩვენებს უკან დაბრუნების ჟესტის ანიმაციას"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"უკან დასაბრუნებლად სენსორულ პანელზე გადაფურცლეთ მარცხნივ ან მარჯვნივ სამი თითის გამოყენებით ნებისმიერ ადგილას.\n\nამისთვის თქვენ ასევე შეგიძლიათ გამოიყენოთ კლავიატურის მალსახმობის მოქმედება + ESC."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"შესანიშნავია!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"თქვენ შეასრულეთ უკან დაბრუნების ჟესტი."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"მთავარზე გადასვლა"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"თქვენს მთავარ ეკრანზე ნებისმიერ დროს გადასასვლელად გადაფურცლეთ ეკრანის ქვემოდან ზემოთ სამი თითით."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"მშვენიერია!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"მოქმედების კლავიში"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"აპებზე წვდომისთვის დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"გილოცავთ!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"თქვენ შეასრულეთ მოქმედების კლავიშის ჟესტი.\n\nქმედება + / აჩვენებს თქვენთვის ხელმისაწვდომ ყველა მალსახმობს."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"კლავიატურის შენათება"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"დონე: %1$d %2$d-დან"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"სახლის კონტროლი"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"მთავარ გვერდზე გადასასვლელად სენსორულ პანელზე გადაფურცლეთ ზემოთ სამი თითით"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ბოლო აპების სანახავად სენსორულ პანელზე სამი თითით გადაფურცლეთ ზემოთ და მოიცადეთ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ყველა აპის სანახავად დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ტექსტს ადევს ცენზურა"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"განბლოკვა სანახავად"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"უკან დასაბრუნებლად გამოიყენეთ სენსორული პანელი"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"გადაფურცლეთ მარცხნივ ან მარჯვნივ სამი თითით. შეეხეთ მეტი ჟესტის შესასწავლად."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"მთავარ გვერდზე გადასასვლელად გამოიყენეთ სენსორული პანელი"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"სამი თითით გადაფურცლეთ ზემოთ და მოიცადეთ. შეეხეთ მეტი ჟესტის შესასწავლად."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ყველა აპის სანახავად გამოიყენეთ თქვენი კლავიატურა"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ნებისმიერ დროს დააჭირეთ მოქმედების კლავიშს. შეეხეთ მეტი ჟესტის შესასწავლად."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"დამატებითი დაბინდვის ფუქნცია ახლა განთავსებულია სიკაშკაშის პანელზე"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ახლა თქვენ შეგიძლიათ დამატებით დაბინდოთ ეკრანი მის ზედა ნაწილში სიკაშკაშის დონის კიდევ უფრო შემცირების გზით.\n\nეს ყველაზე უკეთ ბნელ გარემოში ყოფნისას მუშაობს."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"დამატებითი დაბინდვის მალსახმობის ამოშლა"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"დამატებითი დაბინდვის მალსახმობი ამოშლილია. სიკაშკაშის შესამცირებლად გამოიყენეთ სიკაშკაშის ჩვეულებრივი პანელი."</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 9d84c730aa95..eb3b02f5aecc 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Экран жазғыш"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Жазу басталсын ба?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Жазу кезінде Android жүйесі экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерге, төлем туралы мәліметке, хабарларға, фотосуреттерге, аудиоконтент пен бейнелерге сақ болыңыз."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Қолданбаны жазу кезінде Android жүйесі қолданбада көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Жазуды бастау"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жазу"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Құрылғыдан шығатын дыбыс"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Музыка, қоңыраулар және рингтондар сияқты құрылғыдан шығатын дыбыс"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Жіберу"</string> <string name="cancel" msgid="1089011503403416730">"Бас тарту"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Қолданба логотипі"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Растау"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Қайта көру"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Аутентификациядан бас тарту үшін түртіңіз."</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңа құрылғыны жұптау үшін басыңыз."</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Параметрлер жинағын жаңарту мүмкін болмады."</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Параметрлер жинағы"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Құрылғы микрофонын блоктан шығару керек пе?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Құрылғы камерасын блоктан шығару керек пе?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Құрылғы камерасы мен микрофонын блоктан шығару керек пе?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Өшірулі"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Реттеу"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"\"Параметрлер\" бөлімінде реттеу"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Қосулы режим жоқ}=1{{mode} қосулы}other{# режим қосулы}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Оятқыш, еске салғыш, іс-шара мен өзіңіз көрсеткен контактілердің қоңырауларынан басқа дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойын сияқты медиафайлдарды қоссаңыз, оларды естисіз."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Дабылдардан басқа ешқандай дыбыстар мен дірілдер мазаламайтын болады. Музыка, бейне және ойындар сияқты ойнатылатын контентті ести алатын боласыз."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Реттеу"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Баяу зарядталуда • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Құлыптаулы экрандағы виджеттер"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"\"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" виджеті құлып экранына қосылды."</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Бейімдеу"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабу"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Жазу немесе трансляциялау басталсын ба?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Осы функцияны ұсынатын қызмет экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Бүкіл экран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Жалғыз қолданба"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Қолданба экранын бөлісу не жазу"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> арқылы жазу немесе трансляциялау басталсын ба?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Қолданба экранын бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Бастау"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасымен бөлісу керек пе?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бір қолданбаны бөлісу"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Бүкіл экранды бөлісу"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүкіл экранды бөліскен кезде, ондағы барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Қолданбаны бөліскен кезде, онда көрінетін не ойнатылатын барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлісу"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы осы опцияны өшірді."</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Трансляциялау басталсын ба?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Трансляциялау кезінде Android жүйесі экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Қолданба экранын трансляциялау кезінде Android қолданбада көрінетін не ойнатылатын барлық контентті пайдалана алады. Сондықтан құпия сөздер, төлем туралы мәлімет, хабарлар, фотосуреттер, дыбыстар мен бейнелер сияқты ақпаратқа сақ болыңыз."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Трансляциялауды бастау"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Экранды трансляциялау керек пе?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Бір қолданба экранын трансляциялау"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Бүкіл экранды трансляциялау"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Бүкіл экранды трансляциялаған кезде экранда барлық нәрсе көрсетіледі. Сондықтан құпия сөздерге, төлем туралы мәліметке, хабарларға, фотосуреттерге, аудиоконтент пен бейнелерге сақ болыңыз."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Қолданба экранын трансляциялаған кезде қолданбадағы барлық контент көрсетіледі. Сондықтан құпия сөздерге, төлем туралы мәліметке, хабарларға, фотосуреттерге, аудиоконтент пен бейнелерге сақ болыңыз."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Экранды трансляциялау"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Бөлісу басталсын ба?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Бөлісу, жазу не трансляциялау кезінде Android жүйесі экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Қолданба экранын бөлісу, жазу не трансляциялау кезінде Android жүйесі онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Бастау"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Келесі"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Қолданба ауыстырғанда, бөлісу кідіртіледі."</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Орнына осы қолданбаны бөлісу"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Қайта ауысу"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Арнайы мүмкіндіктер"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Перне тіркесімдері"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Іздеу жылдам пәрмендері"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Іздеу нәтижелері жоқ."</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жию белгішесі"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жаю белгішесі"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"немесе"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Негізгі бетке қайтару қимылы"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Әрекет пернесі"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Дайын"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Жарайсыз!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артқа"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Артқа қайту үшін сенсорлық тақтаның кез келген жерін үш саусақпен солға не оңға сырғытыңыз.\n\nСондай-ақ Action + ESC перне тіркесімін пайдалануға болады."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Негізгі экранға өту"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Негізгі экранға кез келген уақытта өту үшін экранның төменгі жағынан жоғары қарай үш саусағыңызбен сырғытыңыз."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Оңға және солға жылжитын үш саусақты көрсетіп тұрған сенсорлық тақта."</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артқа қайту қимылын көрсетіп тұрған құрылғы экраны."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Деңгей: %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Үй басқару элементтері"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Сенсорлық сақтада үш саусақпен жоғары сырғытсаңыз, негізгі бетке өтесіз."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Сенсорлық тақтада үш саусақпен жоғары сырғытып, басып тұрсаңыз, соңғы ашылған қолданбаларды көресіз."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Пернетақтада әрекет пернесін басып, барлық қолданбаны көре аласыз."</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Жасырылған"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Көру үшін құлыпты ашыңыз."</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Артқа қайту үшін сенсорлық тақтаны қолданыңыз"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Үш саусақпен солға не оңға сырғытыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Негізгі бетке өту үшін сенсорлық тақтаны қолданыңыз"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үш саусақпен жоғары сырғытып, басып тұрыңыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Барлық қолданбаны көру үшін пернетақтаны қолданыңыз"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Әрекет пернесін кез келген уақытта баса аласыз. Басқа қимылдарды үйрену үшін түртіңіз."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Экранды қарайту функциясын енді жарықтық панелінің бөлшегі болады"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Енді экранның жоғарғы бөлігінде жарықтық деңгейін түсіру арқылы экранды одан сайын қарайтуға болады.\n\nБұл мүмкіндіктің артықшылығын қараңғы жерде көруге болады."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Экранды қарайту жылдам пәрменін өшіру"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Экранды қарайту жылдам пәрмені өшірілді. Жарықтықты азайту үшін әдеттегі жарықтық панелін пайдаланыңыз."</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index b84b6b6e9d87..76a266289c6b 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"មុខងារថតវីដេអូអេក្រង់"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុងដំណើរការការថតអេក្រង់"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹងដែលកំពុងដំណើរការសម្រាប់រយៈពេលប្រើការថតសកម្មភាពអេក្រង់"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ចាប់ផ្តើមថតឬ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"នៅពេលអ្នកកំពុងថត, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"នៅពេលអ្នកកំពុងថតកម្មវិធី, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ចាប់ផ្តើមថត"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ថតសំឡេង"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"សំឡេងឧបករណ៍"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"សំឡេងពីឧបករណ៍របស់អ្នកដូចជា តន្ត្រី ការហៅទូរសព្ទ និងសំឡេងរោទ៍ជាដើម"</string> @@ -134,9 +144,9 @@ <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"ឈប់បង្ហាញអេក្រង់ឬ?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"បច្ចុប្បន្ន អ្នកកំពុងបង្ហាញអេក្រង់ទាំងមូលរបស់អ្នកតាមរយៈ <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"បច្ចុប្បន្ន អ្នកកំពុងបង្ហាញអេក្រង់ទាំងមូលរបស់អ្នកតាមរយៈកម្មវិធីមួយ"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"បច្ចុប្បន្ន អ្នកកំពុងបង្ហាញ<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"បច្ចុប្បន្ន អ្នកកំពុងបង្ហាញ <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"បច្ចុប្បន្ន អ្នកកំពុងបង្ហាញកម្មវិធីមួយ"</string> - <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"ឈប់ចែករំលែក"</string> + <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"ឈប់បង្ហាញ"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"កំពុងបញ្ជូនអេក្រង់"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"ឈប់បញ្ជូនឬ?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"បច្ចុប្បន្ន អ្នកកំពុងបញ្ជូនអេក្រង់ទាំងមូលរបស់អ្នកទៅ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ផ្ញើ"</string> <string name="cancel" msgid="1089011503403416730">"បោះបង់"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"និមិត្តសញ្ញាកម្មវិធី"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"បញ្ជាក់"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ព្យាយាមម្ដងទៀត"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ចុចដើម្បីបោះបង់ការផ្ទៀងផ្ទាត់"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ចុច ដើម្បីផ្គូផ្គងឧបករណ៍ថ្មី"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"មិនអាចប្ដូរការកំណត់ជាមុនបានទេ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"កំណត់ជាមុន"</string> - <string name="live_caption_title" msgid="8916875614623730005">"អក្សររត់ក្នុងពេលជាក់ស្ដែង"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"អក្សររត់ក្នុងពេលជាក់ស្ដែង"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ឈប់ទប់ស្កាត់មីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ឈប់ទប់ស្កាត់កាមេរ៉ារបស់ឧបករណ៍ឬ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ឈប់ទប់ស្កាត់កាមេរ៉ា និងមីក្រូហ្វូនរបស់ឧបករណ៍ឬ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ការកំណត់"</string> <string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string> <string name="zen_mode_off" msgid="1736604456618147306">"បិទ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"រៀបចំ"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"គ្រប់គ្រងនៅក្នុងការកំណត់"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{គ្មានមុខងារដែលកំពុងដំណើរការទេ}=1{{mode} កំពុងដំណើរការ}other{មុខងារ # កំពុងដំណើរការ}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ ការរំលឹក ព្រឹត្តិការណ៍ និងអ្នកហៅទូរសព្ទដែលអ្នកបញ្ជាក់ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"សំឡេង និងរំញ័រនឹងមិនរំខានដល់អ្នកឡើយ លើកលែងតែម៉ោងរោទ៍ប៉ុណ្ណោះ។ អ្នកនឹងនៅតែឮសំឡេងសកម្មភាពគ្រប់យ៉ាងដែលអ្នកលេងដដែល រួមទាំងតន្រ្តី វីដេអូ និងហ្គេម។"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ប្ដូរតាមបំណង"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្មយឺត • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ធាតុក្រាហ្វិកនៅលើអេក្រង់ចាក់សោ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"បានបញ្ចូលធាតុក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ទៅអេក្រង់ចាក់សោ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ប្ដូរតាមបំណង"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ច្រានចោល"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> នឹងមានសិទ្ធិចូលប្រើព័ត៌មានទាំងអស់ដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់ពីឧបករណ៍របស់អ្នក នៅពេលកំពុងថត ឬភ្ជាប់។ ព័ត៌មាននេះមានដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ រូបថត សារ និងសំឡេងដែលអ្នកចាក់ជាដើម។"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ចាប់ផ្ដើមថត ឬភ្ជាប់មែនទេ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"សេវាកម្មដែលផ្ដល់មុខងារនេះនឹងមានសិទ្ធិចូលប្រើព័ត៌មានទាំងអស់ដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់ពីឧបករណ៍របស់អ្នក នៅពេលកំពុងថត ឬភ្ជាប់។ ព័ត៌មាននេះមានដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ រូបថត សារ និងសំឡេងដែលអ្នកចាក់ជាដើម។"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"អេក្រង់ទាំងមូល"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"កម្មវិធីតែមួយ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ចែករំលែក ឬថតកម្មវិធី"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"ចាប់ផ្ដើមថត ឬភ្ជាប់ដោយប្រើ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់កម្មវិធី, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ចាប់ផ្ដើម"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"បង្ហាញអេក្រង់របស់អ្នកជាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"បង្ហាញកម្មវិធីមួយ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"បង្ហាញអេក្រង់ទាំងមូល"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"នៅពេលអ្នកបង្ហាញអេក្រង់ទាំងមូលរបស់អ្នក <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងនៅលើអេក្រង់របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"នៅពេលអ្នកបង្ហាញកម្មវិធីណាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងដែលបង្ហាញ ឬចាក់ក្នុងកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"បង្ហាញអេក្រង់"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> បានបិទជម្រើសនេះ"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ចាប់ផ្តើមភ្ជាប់ឬ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"នៅពេលអ្នកកំពុងភ្ជាប់, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"នៅពេលអ្នកកំពុងភ្ជាប់កម្មវិធី, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ចាប់ផ្តើមភ្ជាប់"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"បញ្ជូនអេក្រង់របស់អ្នកឬ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"បញ្ជូនកម្មវិធីមួយ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"បញ្ជូនអេក្រង់ទាំងមូល"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"នៅពេលអ្នកបញ្ជូនអេក្រង់ទាំងមូលរបស់អ្នក អ្នកផ្សេងមើលឃើញអ្វីគ្រប់យ៉ាងនៅលើអេក្រង់របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"នៅពេលអ្នកបញ្ជូនកម្មវិធីណាមួយ អ្នកផ្សេងមើលឃើញអ្វីគ្រប់យ៉ាងដែលបង្ហាញ ឬចាក់ក្នុងកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"បញ្ជូនអេក្រង់"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ចាប់ផ្ដើមចែករំលែកឬ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់កម្មវិធី, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ចាប់ផ្ដើម"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"បន្ទាប់"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ការចែករំលែកផ្អាក នៅពេលដែលអ្នកប្ដូរកម្មវិធី"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ចែករំលែកកម្មវិធីនេះជំនួសវិញ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ប្ដូរទៅវិញ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ភាពងាយស្រួល"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"ផ្លូវកាត់ក្ដារចុច"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ផ្លូវកាត់ការស្វែងរក"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"គ្មានលទ្ធផលស្វែងរកទេ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"រូបតំណាង \"បង្រួម\""</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"រូបតំណាង \"ពង្រីក\""</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ឬ"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ចលនាទៅទំព័រដើម"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"គ្រាប់ចុចសកម្មភាព"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"រួចរាល់"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ធ្វើបានល្អ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ថយក្រោយ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅត្រង់ណាក៏បានលើផ្ទាំងប៉ះ។\n\nអ្នកក៏អាចប្រើសកម្មភាពផ្លូវកាត់ក្ដារចុច + ESC សម្រាប់ការធ្វើបែបនេះ។"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ទៅទំព័រដើម"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ដើម្បីចូលទៅអេក្រង់ដើមរបស់អ្នកនៅពេលណាក៏បាន សូមអូសឡើងលើដោយប្រើម្រាមដៃបីពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក។"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ផ្ទាំងប៉ះដែលបង្ហាញម្រាមដៃបីដែលផ្លាស់ទីទៅស្ដាំ និងឆ្វេង"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"អេក្រង់ឧបករណ៍ដែលបង្ហាញរូបមានចលនាសម្រាប់ចលនាថយក្រោយ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ពន្លឺក្រោយក្ដារចុច"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"កម្រិតទី %1$d នៃ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ការគ្រប់គ្រងផ្ទះ"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ដើម្បីចូលទៅទំព័រដើម សូមអូសឡើងលើដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ដើម្បីមើលកម្មវិធីថ្មីៗ សូមអូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបីនៅលើផ្ទាំងប៉ះ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ដើម្បីមើលកម្មវិធីទាំងអស់របស់អ្នក សូមចុចគ្រាប់ចុចសកម្មភាពនៅលើក្ដារចុចរបស់អ្នក"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"បានកែលម្អពាក្យពេចន៍"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ដោះសោដើម្បីមើល"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីថយក្រោយ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"អូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ប្រើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីចូលទៅទំព័រដើម"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"អូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបី។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ប្រើក្ដារចុចរបស់អ្នក ដើម្បីមើលកម្មវិធីទាំងអស់"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ចុចគ្រាប់ចុចសកម្មភាពនៅពេលណាក៏បាន។ ចុច ដើម្បីស្វែងយល់បន្ថែមអំពីចលនា។"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ឥឡូវនេះ មុខងារងងឹតខ្លាំងក្លាយជាផ្នែកមួយនៃរបារពន្លឺ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ឥឡូវនេះ អ្នកអាចធ្វើឱ្យអេក្រង់ងងឹតខ្លាំងបានដោយបន្ថយកម្រិតពន្លឺបន្ថែមទៀតដោយចូលទៅកាន់ផ្នែកខាងលើនៃអេក្រង់របស់អ្នក។\n\nការធ្វើបែបនេះទទួលបានលទ្ធផលប្រសើរបំផុត ពេលអ្នកស្ថិតនៅកន្លែងងងឹត។"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ដកផ្លូវកាត់មុខងារងងឹតខ្លាំងចេញ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ផ្លូវកាត់មុខងារងងឹតខ្លាំងត្រូវបានដកចេញ។ ដើម្បីបន្ថយពន្លឺរបស់អ្នក សូមប្រើរបារពន្លឺធម្មតា។"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 8ad74af35ede..b97fd31b00f6 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ನೋಟಿಫಿಕೇಶನ್"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ನೀವು ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಿ"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ಸಾಧನದ ಆಡಿಯೋ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ನಿಮ್ಮ ಸಾಧನದ ಧ್ವನಿ ಉದಾ: ಸಂಗೀತ, ಕರೆಗಳು ಮತ್ತು ರಿಂಗ್ಟೋನ್ಗಳು"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ಕಳುಹಿಸಿ"</string> <string name="cancel" msgid="1089011503403416730">"ರದ್ದುಮಾಡಿ"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ಆ್ಯಪ್ ಲೋಗೋ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ದೃಢೀಕರಿಸಿ"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ದೃಢೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -302,7 +310,7 @@ <string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> - <string name="turn_on_bluetooth_auto_tomorrow" msgid="3345758139235739006">"ನಾಳೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಮಾಡಿ"</string> + <string name="turn_on_bluetooth_auto_tomorrow" msgid="3345758139235739006">"ನಾಳೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗಲಿ"</string> <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"ಕ್ವಿಕ್ ಶೇರ್ ಮತ್ತು Find My Device ನಂತಹ ಫೀಚರ್ಗಳು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಬಳಸುತ್ತವೆ"</string> <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"ಬ್ಲೂಟೂತ್ ನಾಳೆ ಬೆಳಗ್ಗೆ ಆನ್ ಆಗುತ್ತದೆ"</string> <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳಿ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ಪ್ರಿಸೆಟ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ಪ್ರಿಸೆಟ್"</string> - <string name="live_caption_title" msgid="8916875614623730005">"ಲೈವ್ ಕ್ಯಾಪ್ಶನ್"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ಲೈವ್ ಕ್ಯಾಪ್ಶನ್"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಅನ್ಬ್ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ಆಫ್ ಆಗಿದೆ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ಸೆಟಪ್ ಮಾಡಿ"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನಿರ್ವಹಿಸಿ"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ಯಾವುದೇ ಸಕ್ರಿಯ ಮೋಡ್ಗಳಿಲ್ಲ}=1{{mode} ಸಕ್ರಿಯವಾಗಿದೆ}one{# ಮೋಡ್ಗಳು ಸಕ್ರಿಯವಾಗಿವೆ}other{# ಮೋಡ್ಗಳು ಸಕ್ರಿಯವಾಗಿವೆ}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ಅಲಾರಾಂಗಳು, ಜ್ಞಾಪನೆಗಳು, ಈವೆಂಟ್ಗಳು ಹಾಗೂ ನೀವು ಸೂಚಿಸಿರುವ ಕರೆದಾರರನ್ನು ಹೊರತುಪಡಿಸಿ ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ನೀವು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ಅಲಾರಾಂಗಳನ್ನು ಹೊರತುಪಡಿಸಿ, ಬೇರಾವುದೇ ಸದ್ದುಗಳು ಅಥವಾ ವೈಬ್ರೇಶನ್ಗಳು ನಿಮಗೆ ತೊಂದರೆ ನೀಡುವುದಿಲ್ಲ. ಹಾಗಿದ್ದರೂ, ನೀವು ಪ್ಲೇ ಮಾಡುವ ಸಂಗೀತ, ವೀಡಿಯೊಗಳು ಮತ್ತು ಆಟಗಳ ಆಡಿಯೊವನ್ನು ಕೇಳಿಸಿಕೊಳ್ಳುತ್ತೀರಿ."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ಕಸ್ಟಮೈಸ್ ಮಾಡು"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳು"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ಗೆ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ವಜಾಗೊಳಿಸಿ"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"ರೆಕಾರ್ಡಿಂಗ್ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುತ್ತದೆ. ಇದು ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ನೀವು ಪ್ಲೇ ಮಾಡುವ ಆಡಿಯೊದಂತಹ ಮಾಹಿತಿಯನ್ನೂ ಒಳಗೊಂಡಿರುತ್ತದೆ."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ರೆಕಾರ್ಡಿಂಗ್ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ಈ ಕಾರ್ಯವನ್ನು ಒದಗಿಸುವ ಸೇವೆಗಳು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಅಥವಾ ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗಳಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಇದು ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ನೀವು ಪ್ಲೇ ಮಾಡುವ ಆಡಿಯೊದಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ಒಂದೇ ಆ್ಯಪ್"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಮೂಲಕ ರೆಕಾರ್ಡಿಂಗ್, ಕ್ಯಾಸ್ಟ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ಪ್ರಾರಂಭಿಸಿ"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ನೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಬೇಕೇ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ಒಂದು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ನಿಮ್ಮ ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನಲ್ಲಿರುವ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸಿರುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡಿದ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ಸ್ಕ್ರೀನ್ ಹಂಚಿಕೊಳ್ಳಿ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಈ ಆಯ್ಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದೆ"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ಕ್ಯಾಸ್ಟ್ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಬೇಕೆ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ನೀವು ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ಕ್ಯಾಸ್ಟ್ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಿ"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡಬೇಕೆ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ಒಂದು ಆ್ಯಪ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡಿ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡಿ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"ನಿಮ್ಮ ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನೀವು ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಏನಾದರೂ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸಿರುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡಿರುವುದು ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬಿತ್ತರಿಸಿ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ಹಂಚಿಕೊಳ್ಳಲು ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ಪ್ರಾರಂಭಿಸಿ"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ಮುಂದಿನದು"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ನೀವು ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗುತ್ತದೆ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ಬದಲಿಗೆ ಈ ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ಮರಳಿ ಬದಲಿಸಿ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್ಕಟ್ಗಳು"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ಹುಡುಕಾಟದ ಶಾರ್ಟ್ಕಟ್ಗಳು"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ಯಾವುದೇ ಹುಡುಕಾಟ ಫಲಿತಾಂಶಗಳಿಲ್ಲ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ಕುಗ್ಗಿಸುವ ಐಕಾನ್"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ವಿಸ್ತೃತಗೊಳಿಸುವ ಐಕಾನ್"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ಅಥವಾ"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ಹೋಮ್ ಗೆಸ್ಚರ್"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ಆ್ಯಕ್ಷನ್ ಕೀ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ಮುಗಿದಿದೆ"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ಭೇಷ್!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ಹಿಂತಿರುಗಿ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ಮೂರು ಬೆರಳುಗಳು ಬಲಕ್ಕೆ ಮತ್ತು ಎಡಕ್ಕೆ ಚಲಿಸುತ್ತಿರುವುದನ್ನು ತೋರಿಸುತ್ತಿರುವ ಟಚ್ಪ್ಯಾಡ್"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ಗೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯನಿಮೇಶನ್ ಅನ್ನು ತೋರಿಸುತ್ತಿರುವ ಸಾಧನದ ಸ್ಕ್ರೀನ್"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ಹಿಂತಿರುಗಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಎಲ್ಲಿಯಾದರೂ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಎಡ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ.\n\nಇದಕ್ಕಾಗಿ ನೀವು ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್ಕಟ್ Action + ESC ಅನ್ನು ಸಹ ಬಳಸಬಹುದು."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ಭೇಷ್!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ನೀವು ಗೋ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಿ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಕೆಳಗಿನಿಂದ ಮೂರು ಬೆರಳುಗಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ಭೇಷ್!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ನೀವು ಗೋ ಹೋಮ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"ಆ್ಯಕ್ಷನ್ ಕೀ"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ನಿಮ್ಮ ಆ್ಯಪ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು, ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ನಲ್ಲಿರುವ ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಒತ್ತಿರಿ."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ಅಭಿನಂದನೆಗಳು!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ನೀವು ಆ್ಯಕ್ಷನ್ ಕೀ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ.\n\nನಿಮಗೆ ಲಭ್ಯವಿರುವ ಎಲ್ಲಾ ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಆ್ಯಕ್ಷನ್ + / ತೋರಿಸುತ್ತದೆ."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್ಲೈಟ್"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ರಲ್ಲಿ %1$d ಮಟ್ಟ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ಮನೆ ನಿಯಂತ್ರಣಗಳು"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ಹೋಮ್ಗೆ ಹೋಗಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್ಗಳನ್ನು ನೋಡಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಹಾಗೂ ಹೋಲ್ಡ್ ಮಾಡಿ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ನಿಮ್ಮ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು, ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ನಲ್ಲಿರುವ ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಒತ್ತಿರಿ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ಅರ್ಥಬದ್ಧವಾಗಿಸಲಾಗಿದೆ"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ನೋಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ಹಿಂತಿರುಗಲು ನಿಮ್ಮ ಟಚ್ಪ್ಯಾಡ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ಮೂರು ಬೆರಳುಗಳಿಂದ ಎಡಕ್ಕೆ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ. ಇನ್ನಷ್ಟು ಗೆಸ್ಚರ್ಗಳನ್ನು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ಹೋಮ್ಗೆ ಹೋಗಲು ನಿಮ್ಮ ಟಚ್ಪ್ಯಾಡ್ ಅನ್ನು ಬಳಸಿ"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ಮೂರು ಬೆರಳುಗಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಹಾಗೂ ಹೋಲ್ಡ್ ಮಾಡಿ. ಇನ್ನಷ್ಟು ಗೆಸ್ಚರ್ಗಳನ್ನು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ಯಾವಾಗ ಬೇಕಾದರೂ ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಒತ್ತಿರಿ. ಇನ್ನಷ್ಟು ಗೆಸ್ಚರ್ಗಳನ್ನು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಈಗ ಬ್ರೈಟ್ನೆಸ್ ಬಾರ್ನ ಭಾಗವಾಗಿದೆ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲ್ಭಾಗದಿಂದ ಬ್ರೈಟ್ನೆಸ್ ಮಟ್ಟವನ್ನು ಇನ್ನಷ್ಟು ಕಡಿಮೆ ಮಾಡುವ ಮೂಲಕ ನೀವು ಈಗ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಇನ್ನಷ್ಟು ಮಬ್ಬುಗೊಳಿಸಬಹುದು.\n\nನೀವು ಕತ್ತಲೆಯ ವಾತಾವರಣದಲ್ಲಿರುವಾಗ ಇದು ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ. ನಿಮ್ಮ ಬ್ರೈಟ್ನೆಸ್ ಅನ್ನು ಕಡಿಮೆ ಮಾಡಲು, ಸಾಮಾನ್ಯ ಬ್ರೈಟ್ನೆಸ್ ಬಾರ್ ಬಳಸಿ."</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index b904fa8023b7..f51e35542e80 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"화면 녹화"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"녹화를 시작하시겠습니까?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"녹화 중에는 Android가 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"앱을 녹화할 때 Android가 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"녹화 시작"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"오디오 녹음"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"기기 오디오"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"음악, 통화, 벨소리와 같이 기기에서 나는 소리"</string> @@ -128,20 +138,20 @@ <string name="screenrecord_start_error" msgid="2200660692479682368">"화면 녹화 시작 중 오류 발생"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"녹화를 중지하시겠습니까?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"현재 전체 화면을 녹화 중입니다."</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g>의 콘텐츠를 녹화 중입니다"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g>의 콘텐츠를 녹화 중입니다."</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"녹화 중지"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"화면 공유 중"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"화면 공유를 중지하시겠습니까?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"현재 전체 화면을 <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>과 공유 중입니다"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"현재 전체 화면을 <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> 앱과 공유 중입니다."</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"현재 전체 화면을 앱과 공유 중입니다"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"현재 <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>의 콘텐츠를 공유 중입니다"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"현재 <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>의 콘텐츠를 공유 중입니다."</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"현재 앱을 공유 중입니다"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"공유 중지"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"화면 전송 중"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"전송을 중지할까요?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"현재 전체 화면을 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>로 전송 중입니다."</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"현재 전체 화면을 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기로 전송 중입니다."</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"현재 전체 화면을 근처 기기로 전송 중입니다."</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"현재 <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>의 콘텐츠를 <xliff:g id="DEVICE_NAME">%2$s</xliff:g>로 전송 중입니다."</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"현재 <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>의 콘텐츠를 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 기기로 전송 중입니다."</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"현재 <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>의 콘텐츠를 근처 기기로 전송 중입니다."</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"현재 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>로 전송 중입니다."</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"현재 근처 기기로 전송 중입니다."</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"보내기"</string> <string name="cancel" msgid="1089011503403416730">"취소"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"앱 로고"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"확인"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"다시 시도하세요."</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"탭하여 인증 취소"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"새 기기와 페어링하려면 클릭하세요"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"사전 설정을 업데이트할 수 없음"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"미리 설정"</string> - <string name="live_caption_title" msgid="8916875614623730005">"실시간 자막"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"실시간 자막"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"기기 카메라를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"기기 카메라 및 마이크를 차단 해제하시겠습니까?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"설정"</string> <string name="zen_mode_on" msgid="9085304934016242591">"사용"</string> <string name="zen_mode_off" msgid="1736604456618147306">"사용 안함"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"설정"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"설정에서 관리"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{활성화된 모드 없음}=1{{mode} 모드가 활성화됨}other{모드 #개가 활성화됨}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"알람, 알림, 일정 및 지정한 발신자로부터 받은 전화를 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"알람을 제외한 소리와 진동을 끕니다. 음악, 동영상, 게임 등 재생하도록 선택한 소리는 정상적으로 들립니다."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"맞춤설정"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 저속 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"잠금 화면의 위젯"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> 위젯이 잠금 화면에 추가됨"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"맞춤설정"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"닫기"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱이 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 사용자가 재생하는 오디오 등의 정보가 포함됩니다."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"녹화 또는 전송을 시작하시겠습니까?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 사용자가 재생하는 오디오 등의 정보가 포함됩니다."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"전체 화면"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"단일 앱"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"앱 공유 또는 녹화"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱으로 녹화 또는 전송을 시작하시겠습니까?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"공유, 녹화 또는 전송 중에 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱이 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"앱을 공유, 녹화 또는 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱이 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"시작"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"화면을 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱과 공유하시겠습니까?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"앱 하나 공유"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"전체 화면 공유"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"전체 화면을 공유하면 화면에 있는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"앱을 공유하면 앱에 표시되거나 앱에서 재생되는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"화면 공유"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 이 옵션을 사용 중지했습니다."</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"전송을 시작하시겠습니까?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"전송 중에는 Android가 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"앱을 전송할 때 Android가 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"전송 시작하기"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"화면을 전송하시겠습니까?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"앱 1개 전송"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"전체 화면 전송"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"전체 화면을 전송하면 화면이 있는 모든 항목이 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"앱을 전송하면 해당 앱에 표시되거나 재생되는 모든 항목이 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"화면 전송"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"공유를 시작하시겠습니까?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"공유, 녹화 또는 전송 중에 Android가 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"앱을 공유, 녹화 또는 전송할 때는 Android가 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"시작"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"다음"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"앱을 전환할 때 공유를 일시중지합니다."</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"대신 이 앱 공유"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"다시 전환"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"접근성"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"단축키"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"검색 바로가기"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"검색 결과 없음"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"접기 아이콘"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"확장 아이콘"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"또는"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"홈 동작"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"작업 키"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"완료"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"아주 좋습니다."</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"뒤로"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"돌아가려면 세 손가락을 사용해 터치패드의 아무 곳이나 왼쪽 또는 오른쪽으로 스와이프합니다.\n\n키보드 단축키 Action + ESC를 사용할 수도 있습니다."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"홈으로 이동"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"언제든지 홈 화면으로 이동하려면 세 손가락으로 화면 하단에서 위로 스와이프하세요."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"터치패드에서 세 손가락을 좌우로 움직이는 모습"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"뒤로 동작 애니메이션을 보여 주는 기기 화면"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d단계 중 %1$d단계"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"홈 컨트롤"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"홈으로 이동하려면 터치패드에서 세 손가락을 사용해 위로 스와이프합니다"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"최근 앱을 보려면 터치패드에서 세 손가락으로 위로 스와이프한 후 잠시 기다리세요"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"모든 앱을 보려면 키보드의 작업 키를 누르세요"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"수정됨"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"잠금 해제하여 보기"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"터치패드를 사용하여 돌아가기"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"세 손가락을 사용해 왼쪽 또는 오른쪽으로 스와이프하세요. 더 많은 동작을 알아보려면 탭하세요."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"터치패드를 사용하여 홈으로 이동"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"세 손가락을 사용해 위로 스와이프한 다음 잠시 기다리세요. 더 많은 동작을 알아보려면 탭하세요."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"키보드를 사용하여 모든 앱 보기"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"언제든지 작업 키를 누릅니다. 더 많은 동작을 알아보려면 탭하세요."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"이제 \'더 어둡게\' 기능이 밝기 막대에 추가되었습니다"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"이제 화면 상단에서 밝기 수준을 더 낮춰 화면을 더 어둡게 만들 수 있습니다\n\n이 기능은 어두운 환경에서 가장 잘 작동합니다."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'더 어둡게\' 단축키 삭제"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'더 어둡게\' 단축키가 삭제되었습니다. 밝기를 낮추려면 일반 밝기 막대를 사용하세요."</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 7cea137cb77c..274b07d30aeb 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Экрандан видео жаздырып алуу"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Жаздырып баштайсызбы?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Жаздырып жатканыңызда Android экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Колдонмону жаздырып жатканда Android анда көрүнүп же ойноп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Жаздырып баштоо"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио жаздыруу"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Түзмөктөгү аудиолор"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Музыка, чалуулар жана шыңгырлар сыяктуу түзмөгүңүздөгү добуштар"</string> @@ -131,17 +141,17 @@ <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Учурда <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун жаздырып жатасыз"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Жаздырууну токтотуу"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Экран бөлүшүлүүдө"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Экранды бөлүшүү токтотулсунбу?"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Экранды бөлүшүүнү токтотосузбу?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Учурда бүтүндөй экраныңызды <xliff:g id="HOST_APP_NAME">%1$s</xliff:g> менен бөлүшүп жатасыз"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Учурда бүтүндөй экраныңызды колдонмо менен бөлүшүп жатасыз"</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Учурда <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> колдонмосун бөлүшүп жатасыз"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Учурда колдонмону бөлүшүп жатасыз"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Бөлүшүүнү токтотуу"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Тышкы экранга чыгарылууда"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Тышкы экранга чыгаруу токтотулсунбу?"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Тышкы экранга чыгарууну токтотосузбу?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Учурда бүтүндөй экраныңызды <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө чыгарып жатасыз"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Учурда бүтүндөй экраныңызды жакын жердеги түзмөккө чыгарып жатасыз"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Учурда <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> контентин <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүнө чыгарып жатасыз"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Учурда <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> колдонмосун <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүнө чыгарып жатасыз"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> контентин жакын жердеги түзмөккө чыгарып жатасыз"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Учурда <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө чыгарып жатасыз"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Учурда жакын жердеги түзмөккө чыгарып жатасыз"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Жөнөтүү"</string> <string name="cancel" msgid="1089011503403416730">"Баш тартуу"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Колдонмонун логотиби"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Ырастоо"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Кайталоо"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Аныктыгын текшерүүнү жокко чыгаруу үчүн таптаңыз"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Жаңы түзмөк кошуу үчүн басыңыз"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Алдын ала коюлган параметрлер жаңыртылган жок"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Алдын ала коюлган параметрлер"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Ыкчам коштомо жазуулар"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Ыкчам коштомо жазуулар"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Түзмөктүн микрофонун бөгөттөн чыгарасызбы?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Түзмөктүн камерасын бөгөттөн чыгарасызбы?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Түзмөктүн камерасы менен микрофону бөгөттөн чыгарылсынбы?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Өчүк"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Тууралоо"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Параметрлерден тескөө"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Жигердүү режимдер жок}=1{{mode} иштеп жатат}other{# режим иштеп жатат}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ойготкучтардан, эскертүүлөрдөн, жылнаамадагы иш-чараларды эстеткичтерден жана белгиленген байланыштардын чалууларынан тышкары башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ойготкучтардан башка үндөр жана дирилдөөлөр тынчыңызды албайт. Бирок ойнотулуп жаткан музыканы, видеолорду жана оюндарды мурдагыдай эле уга бересиз."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Ыңгайлаштыруу"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Жай кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Кулпуланган экрандагы виджеттер"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети кулпу экранына кошулду"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Ыңгайлаштыруу"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабуу"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Жаздырып же тышкы экранга чыгарып жатканда <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Жаздырып же тышкы экранга чыгарып баштайсызбы?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Жаздырып же тышкы экранга чыгарып жатканда кызмат көрсөтүүчү экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Бүтүндөй экран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Жалгыз колдонмо"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Колдонмону бөлүшүү же жаздыруу"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу аркылуу жаздырып же тышкы экранга чыгарып баштайсызбы?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Бөлүшүп, жаздырып же тышкы экранга чыгарып жатканда <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Колдонмону бөлүшүп, жаздырып же тышкы экранга чыгарганда <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу анда көрүнүп же ойноп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Баштоо"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> менен бөлүшөсүзбү?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бир колдонмону бөлүшүү"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Толук экранды бөлүшүү"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүтүндөй экранды бөлүшкөндө андагы бардык нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Колдонмону бөлүшкөндө ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлүшүү"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> бул параметрди өчүрүп койду"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Тышкы экранга чыгарып баштайсызбы?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Тышкы экранга чыгарганда Android экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Колдонмону тышкы экранга чыгарганда Android анда көрүнүп же ойноп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Тышкы экранга чыгарып баштоо"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Экранды тышкы экранга чыгарасызбы?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Бир колдонмону тышкы экранга чыгаруу"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Бүтүндөй экранды тышкы экранга чыгаруу"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Бүтүндөй экранды тышкы экранга чыгарганда андагы бардык нерселер көрүнөт. Андыктан сырсөздөр, төлөмдүн чоо-жайы, билдирүүлөр, сүрөттөр, аудио жана видео сыяктуу нерселерди көрсөтүп албаңыз."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Колдонмону тышкы экранга чыгарганда ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер көрүнөт. Андыктан сырсөздөр, төлөмдүн чоо-жайы, билдирүүлөр, сүрөттөр, аудио жана видео сыяктуу нерселерди көрсөтүп албаңыз."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Тышкы экранга чыгаруу"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Бөлүшүү башталсынбы?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Бөлүшүп, жаздырып же тышкы экранга чыгарып жатканда Android экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Колдонмону бөлүшүп, жаздырып же тышкы экранга чыгарганда Android анда көрүнүп же ойноп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Баштоо"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Кийинки"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Колдонмо которулганда бөлүшүү тындырылат"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Анын ордуна бул колдонмону бөлүшүү"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Кайра которулуу"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Атайын мүмкүнчүлүктөр"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Ыкчам баскычтар"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Ыкчам баскычтарды издөө"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Эч нерсе табылган жок"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жыйыштыруу сүрөтчөсү"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жайып көрсөтүү сүрөтчөсү"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"же"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Башкы бетке өтүү жаңсоосу"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Аракет баскычы"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Бүттү"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Азаматсыз!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артка кайтуу"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Кайтуу үчүн сенсордук тактанын каалаган жерин үч манжаңыз менен солго же оңго сүрүңүз.\n\nОшондой эле Action + ESC баскычтарынын айкалышын колдоно аласыз."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Башкы бетке өтүү"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Каалаган убакта башкы экранга өтүү үчүн экранды үч манжаңыз менен ылдыйдан жогору карай сүрүңүз."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Үч манжанын оңго жана солго жылып жатканы көрсөтүлгөн сенсордук такта"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Артка жаңсоосунун анимациясы көрсөтүлгөн түзмөктүн экраны"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ичинен %1$d-деңгээл"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Үйдөгү түзмөктөрдү тескөө"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Башкы бетке өтүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүңүз"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Акыркы колдонмолорду көрүү үчүн сенсордук тактаны үч манжаңыз менен өйдө сүрүп, кармап туруңуз"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бардык колдонмолоруңузду көрүү үчүн баскычтобуңуздагы аракет баскычын басыңыз"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Жашырылды"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Көрүү үчүн кулпусун ачыңыз"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Артка кайтуу үчүн сенсордук тактаны колдонуңуз"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Үч манжаңыз менен солго же оңго сүрүңүз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Башкы бетке өтүү үчүн сенсордук тактаны колдонуңуз"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Үч манжаңыз менен өйдө сүрүп, кармап туруңуз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бардык колдонмолорду көрүү үчүн баскычтобуңузду колдонуңуз"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Каалаганда аракет баскычын басыңыз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Кошумча караңгылатуу эми жарыктык тилкесинде жайгашкан"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Эми экраныңыздын өйдө жагынан жарыктыктын деңгээлин азайтып, экранды кошумча караңгылата аласыз.\n\nМуну караңгы жерде турганыңызда колдонуу сунушталат."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Кошумча караңгылатуу ыкчам баскычын өчүрүү"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Кошумча караңгылатуу ыкчам баскычы өчүрүлдү. Жарыктыкты азайтуу үчүн кадимки жарыктык тилкесин колдонуңуз."</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 2c490ac84c9d..fd6bb54201eb 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ເລີ່ມການບັນທຶກບໍ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ໃນຂະນະທີ່ທ່ານກຳລັງບັນທຶກ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ໃນຂະນະທີ່ທ່ານກຳລັງບັນທຶກແອັບ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ເລີ່ມການບັນທຶກ"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ບັນທຶກສຽງ"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ສຽງອຸປະກອນ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ສຽງຈາກອຸປະກອນຂອງທ່ານ ເຊັ່ນ: ສຽງເພງ, ສຽງລົມໂທລະສັບ ແລະ ສຽງຣິງໂທນ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ສົ່ງ"</string> <string name="cancel" msgid="1089011503403416730">"ຍົກເລີກ"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ໂລໂກ້ແອັບ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ຢືນຢັນ"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ລອງໃໝ່"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ແຕະເພື່ອຍົກເລີກການກວດສອບຄວາມຖືກຕ້ອງ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ຄລິກເພື່ອຈັບຄູ່ອຸປະກອນໃໝ່"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ບໍ່ສາມາດອັບເດດການຕັ້ງຄ່າລ່ວງໜ້າໄດ້"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ຄ່າທີ່ກຳນົດລ່ວງໜ້າ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"ຄຳບັນຍາຍສົດ"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ຄຳບັນຍາຍສົດ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ປົດບລັອກໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ປົດບລັອກກ້ອງຖ່າຍຮູບອຸປະກອນບໍ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ຍົກເລີກການບລັອກກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນອຸປະກອນບໍ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ການຕັ້ງຄ່າ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ປິດ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ຕັ້ງຄ່າ"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ຈັດການໃນການຕັ້ງຄ່າ"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ບໍ່ມີໂໝດທີ່ເຮັດວຽກຢູ່}=1{{mode} ເຮັດວຽກຢູ່}other{# ໂໝດເຮັດວຽກຢູ່}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ, ມີການແຈ້ງເຕືອນ ຫຼື ມີສາຍໂທເຂົ້າຈາກຜູ້ໂທທີ່ທ່ານລະບຸໄວ້. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ທ່ານຈະບໍ່ໄດ້ຮັບການລົບກວນຈາກສຽງ ແລະ ການສັ່ນເຕືອນ, ຍົກເວັ້ນໃນເວລາໂມງປຸກດັງ. ທ່ານອາດຍັງຄົງໄດ້ຍິນຫາກທ່ານເລືອກຫຼິ້ນເພງ, ວິດີໂອ ແລະ ເກມ."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ປັບແຕ່ງ"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟແບບຊ້າ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ວິດເຈັດຢູ່ໜ້າຈໍລັອກ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"ເພີ່ມວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ໃສ່ໜ້າຈໍລັອກແລ້ວ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ປັບແຕ່ງ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ປ່ອຍໄປ"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນຂະນະທີ່ບັນທຶກ ຫຼື ສົ່ງສັນຍານ. ເຊິ່ງຈະຮວມທັງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບພາບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ເລີ່ມການບັນທຶກ ຫຼື ການສົ່ງສັນຍານບໍ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ບໍລິການທີ່ມີຟັງຊັນນີ້ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນຂະນະທີ່ບັນທຶກ ຫຼື ສົ່ງສັນຍານ. ເຊິ່ງຈະຮວມທັງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບພາບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ທັງໝົດໜ້າຈໍ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ແອັບດຽວ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ແບ່ງປັນ ຫຼື ບັນທຶກແອັບ"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"ເລີ່ມການບັນທຶກ ຫຼື ການສົ່ງສັນຍານດ້ວຍ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ເລີຍບໍ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານແອັບ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ເລີ່ມ"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ແບ່ງປັນໜ້າຈໍຂອງທ່ານກັບ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ບໍ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ແບ່ງປັນແອັບດຽວ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ແບ່ງປັນໜ້າຈໍທັງໝົດ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ເມື່ອທ່ານແບ່ງປັນໜ້າຈໍທັງໝົດຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ຢູ່ໜ້າຈໍຂອງທ່ານໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ເມື່ອທ່ານແບ່ງປັນແອັບຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ສະແດງ ຫຼື ຫຼິ້ນໃນແອັບໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ແບ່ງປັນໜ້າຈໍ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ປິດການນຳໃຊ້ຕົວເລືອກນີ້ແລ້ວ"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ເລີ່ມການສົ່ງສັນຍານບໍ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ເມື່ອທ່ານກຳລັງສົ່ງສັນຍານ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ເມື່ອທ່ານກຳລັງສົ່ງສັນຍານແອັບ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ເລີ່ມການສົ່ງສັນຍານ"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ສົ່ງສັນຍານໜ້າຈໍຂອງທ່ານບໍ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ສົ່ງສັນຍານແອັບ 1 ລາຍການ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"ສົ່ງສັນຍານໜ້າຈໍທັງໝົດ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"ເມື່ອທ່ານສົ່ງສັນຍານໜ້າຈໍທັງໝົດຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ຢູ່ໜ້າຈໍຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ເມື່ອທ່ານສົ່ງສັນຍານແອັບ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ສະແດງ ຫຼື ຫຼິ້ນໃນແອັບ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"ສົ່ງສັນຍານໜ້າຈໍ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ເລີ່ມການແບ່ງປັນບໍ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານແອັບ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ເລີ່ມ"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ຕໍ່ໄປ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ການແບ່ງປັນຈະຢຸດຊົ່ວຄາວເມື່ອທ່ານປ່ຽນແອັບ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ແບ່ງປັນແອັບນີ້ແທນ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ປ່ຽນກັບຄືນ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ການຊ່ວຍເຂົ້າເຖິງ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"ຄີລັດ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ທາງລັດການຊອກຫາ"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ບໍ່ມີຜົນການຊອກຫາ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ໄອຄອນຫຍໍ້ລົງ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ໄອຄອນຂະຫຍາຍ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ຫຼື"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ທ່າທາງສຳລັບໜ້າຫຼັກ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ປຸ່ມຄຳສັ່ງ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ແລ້ວໆ"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ດີຫຼາຍ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ກັບຄືນ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ເພື່ອກັບຄືນ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຊ້າຍ ຫຼື ຂວາບ່ອນໃດກໍໄດ້ເທິງແຜ່ນສຳຜັດ.\n\nທ່ານຍັງສາມາດໃຊ້ຄຳສັ່ງຄີລັດ + ESC ສຳລັບການດຳເນີນການນີ້ໄດ້ນຳ."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ໄປຫາໜ້າຫຼັກ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ເພື່ອໄປຫາໜ້າຫຼັກຂອງທ່ານຕອນໃດກໍໄດ້, ໃຫ້ປັດຂຶ້ນດ້ວຍສາມນິ້ວຈາກລຸ່ມສຸດຂອງໜ້າຈໍຂອງທ່ານ."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ແຜ່ນສໍາຜັດສະແດງພາບ 3 ນິ້ວເລື່ອນໄປທາງຂວາ ແລະ ຊ້າຍ"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ໜ້າຈໍອຸປະກອນສະແດງພາບເຄື່ອນໄຫວຂອງທ່າທາງກັບຄືນ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ໄຟປຸ່ມແປ້ນພິມ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ລະດັບທີ %1$d ຈາກ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ການຄວບຄຸມເຮືອນ"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ເພື່ອໄປຫາໜ້າຫຼັກ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຂຶ້ນເທິງແຜ່ນສໍາຜັດ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ເພື່ອເບິ່ງແອັບຫຼ້າສຸດ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຂຶ້ນ ແລ້ວຄ້າງໄວ້ເທິງແຜ່ນສໍາຜັດ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ເພື່ອເບິ່ງແອັບທັງໝົດຂອງທ່ານ, ໃຫ້ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ປົກປິດໄວ້ແລ້ວ"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ປົດລັອກເພື່ອເບິ່ງ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ໃຊ້ແຜ່ນສໍາຜັດຂອງທ່ານເພື່ອກັບຄືນ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ໃຊ້ 3 ນິ້ວປັດຊ້າຍ ຫຼື ຂວາ. ແຕະເພື່ອສຶກສາທ່າທາງເພີ່ມເຕີມ."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ໃຊ້ແຜ່ນສໍາຜັດຂອງທ່ານເພື່ອໄປຫາໜ້າຫຼັກ"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ໃຊ້ 3 ນິ້ວປັດຂຶ້ນ ແລ້ວຄ້າງໄວ້. ແຕະເພື່ອສຶກສາທ່າທາງເພີ່ມເຕີມ."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ໃຊ້ແປ້ນພິມຂອງທ່ານເພື່ອເບິ່ງແອັບທັງໝົດ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ກົດປຸ່ມຄຳສັ່ງໄດ້ທຸກເວລາ. ແຕະເພື່ອສຶກສາທ່າທາງເພີ່ມເຕີມ."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ຕອນນີ້ການຫຼຸດແສງເປັນພິເສດເປັນສ່ວນໜຶ່ງຂອງແຖບຄວາມສະຫວ່າງແລ້ວ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ຕອນນີ້ທ່ານສາມາດເຮັດໃຫ້ໜ້າຈໍມືດລົງເປັນພິເສດໄດ້ໂດຍການຫຼຸດລະດັບຄວາມສະຫວ່າງລົງໃຫ້ຫຼາຍຂຶ້ນຈາກເທິງສຸດຂອງໜ້າຈໍຂອງທ່ານ.\n\nຄຸນສົມບັດນີ້ຈະເຮັດວຽກໄດ້ດີທີ່ສຸດເມື່ອທ່ານຢູ່ໃນສະພາບແວດລ້ອມທີ່ມືດ."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ລຶບທາງລັດທີ່ຫຼຸດແສງເປັນພິເສດອອກ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ລຶບທາງລັດທີ່ຫຼຸດແສງເປັນພິເສດອອກແລ້ວ. ເພື່ອຫຼຸດຄວາມສະຫວ່າງຂອງທ່ານລົງ, ໃຫ້ໃຊ້ແຖບຄວາມສະຫວ່າງປົກກະຕິ."</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 6b97dc996498..b5efb42ce961 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekrano vaizdo įrašytuvas"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Pradėti įrašymą?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Kai įrašote, „Android“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kai įrašote programą, „Android“ gali pasiekti viską, kas rodoma ar leidžiama toje programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Pradėti įrašymą"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Įrašyti garsą"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Įrenginio garsas"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Garsas iš jūsų įrenginio, pvz., muzika, skambučiai ir skambėjimo tonai"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Siųsti"</string> <string name="cancel" msgid="1089011503403416730">"Atšaukti"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Programos logotipas"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Patvirtinkite"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Bandyti dar kartą"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Palieskite, jei norite atšaukti autentifikavimą"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Spustelėkite, kad susietumėte naują įrenginį"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Išankstinių nustatymų atnaujinti nepavyko"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Išankstiniai nustatymai"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtitrai realiuoju laiku"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitrai realiuoju laiku"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Panaikinti įrenginio mikrofono blokavimą?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Panaikinti įrenginio fotoaparato blokavimą?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Panaikinti įrenginio fotoaparato ir mikrofono blokavimą?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nustatymai"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Išjungta"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Nustatyti"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Tvarkyti skiltyje „Nustatymai“"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nėra aktyvių režimų}=1{Aktyvus režimas „{mode}“}one{# aktyvus režimas}few{# aktyvūs režimai}many{# aktyvaus režimo}other{# aktyvių režimų}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jūsų netrikdys garsai ir vibravimas, išskyrus nurodytų signalų, priminimų, įvykių ir skambintojų garsus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūsų netrikdys garsai ir vibravimas, išskyrus signalus. Vis tiek girdėsite viską, ką pasirinksite leisti, įskaitant muziką, vaizdo įrašus ir žaidimus."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Tinkinti"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lėtai įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Valdikliai užrakinimo ekrane"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Valdiklis „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ pridėtas prie užrakinimo ekrano"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tinkinti"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Atsisakyti"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Pradėti įrašyti ar perduoti turinį?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Šią funkciją teikianti paslauga galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Visas ekranas"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Viena programa"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Programos bendrinimas ar įrašymas"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Pradėti įrašyti ar perduoti turinį naudojant „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kai bendrinate, įrašote ar perduodate turinį, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kai bendrinate, įrašote ar perduodate programą, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali pasiekti viską, kas rodoma ar leidžiama programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pradėti"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bendrinti ekraną su „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bendrinti vieną programą"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bendrinti visą ekraną"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kai bendrinate visą ekraną, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas ekrano turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kai bendrinate programą, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas toje programoje rodomas ar leidžiamas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bendrinti ekraną"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Programoje „<xliff:g id="APP_NAME">%1$s</xliff:g>“ ši parinktis išjungta"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Pradėti perdavimą?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kai perduodate turinį, „Android“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kai perduodate programą, „Android“ gali pasiekti viską, kas rodoma ar leidžiama toje programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Pradėti perdavimą"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Perduoti ekraną?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Perduoti vieną programą"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Perduoti visą ekraną"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kai perduodate visą ekraną, matomas visas ekrano turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kai perduodate programą, matomas visas toje programoje rodomas ar leidžiamas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Perduoti ekraną"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Pradėti bendrinti?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kai bendrinate, įrašote ar perduodate turinį, „Android“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kai bendrinate, įrašote ar perduodate programą, „Android“ gali pasiekti viską, kas rodoma ar leidžiama programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Pradėti"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Kitas"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Bendrinimas pristabdomas, kai perjungiate programas"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Bendrinti šią programą"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Perjungti atgal"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pritaikomumas"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Spartieji klavišai"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Paieškos šaukiniai"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nėra jokių paieškos rezultatų"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sutraukimo piktograma"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Išskleidimo piktograma"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"arba"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pagrindinio ekrano gestas"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Veiksmų klavišas"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Atlikta"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Puiku!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Grįžti"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Jei norite grįžti, perbraukite kairėn arba dešinėn trimis pirštais bet kurioje jutiklinės dalies vietoje.\n\nTaip pat galite naudoti šį spartųjį klavišą: veiksmų klavišas + klavišas „Esc“."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Eikite į pagrindinį ekraną"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Jei norite bet kada pasiekti pagrindinį ekraną, perbraukite aukštyn trim pirštais iš ekrano apačios."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Jutiklinė dalis, kurioje rodomi trys dešinėn ir kairėn judantys pirštai"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Įrenginio ekranas, kuriame rodoma grįžimo gesto animacija"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatūros foninis apšvietimas"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d lygis iš %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Namų sistemos valdymas"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Jei norite eiti į pagrindinį ekraną, jutiklinėje dalyje perbraukite aukštyn trimis pirštais"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Peržiūrėkite naujausias programas, jutiklinėje dalyje perbraukę aukštyn trimis pirštais ir palaikę"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Jei norite peržiūrėti visas programas, paspauskite klaviatūros veiksmų klavišą"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Paslėpta"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Atrakinkite, kad peržiūrėtumėte"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Naudokite klaviatūrą, kad grįžtumėte atgal"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Perbraukite į kairę ar dešinę trimis pirštais. Palieskite, kad sužinotumėte daugiau gestų."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Naudokite jutiklinę dalį, jei norite eiti į pagrindinį ekraną"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Perbraukite aukštyn trimis pirštais ir palaikykite. Palieskite, kad sužinotumėte daugiau gestų."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Naudokite klaviatūrą, kad peržiūrėtumėte visas programas"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bet kuriuo metu paspauskite veiksmų klavišą. Palieskite, kad sužinotumėte daugiau gestų."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funkcija „Itin blanku“ dabar yra ryškumo juostos dalis"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Dabar galite padaryti ekraną itin blankų, dar labiau sumažindami ryškumo lygį nuo ekrano viršaus.\n\nŠi funkcija geriausiai veikia, kai esate tamsioje aplinkoje."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Pašalinti funkcijos „Itin blanku“ spartųjį klavišą"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Funkcijos „Itin blanku“ spartusis klavišas pašalintas. Jei norite sumažinti ryškumą, naudokite įprastą ryškumo juostą."</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index f191a2826d96..34376fd2a8e8 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekrāna ierakstītājs"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Vai sākt ierakstīšanu?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Ierakstīšanas laikā Android var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Lietotnes ierakstīšanas laikā Android var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu rīkojieties piesardzīgi."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Sākt ierakstīšanu"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Ierakstīt audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Ierīces audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Skaņa no jūsu ierīces, piemēram, mūzika, sarunas un zvana signāli"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Sūtīt"</string> <string name="cancel" msgid="1089011503403416730">"Atcelt"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Lietotnes logotips"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Apstiprināt"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Mēģināt vēlreiz"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Pieskarieties, lai atceltu autentifikāciju."</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Noklikšķiniet, lai savienotu pārī jaunu ierīci"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nevarēja atjaunināt pirmsiestatījumu"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Pirmsiestatījums"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtitri reāllaikā"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitri reāllaikā"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vai atbloķēt ierīces mikrofonu?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vai vēlaties atbloķēt ierīces kameru?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vai atbloķēt ierīces kameru un mikrofonu?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Iestatījumi"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Izslēgts"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Iestatīt"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Pārvaldīt iestatījumos"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nav aktīvu režīmu}=1{Režīms “{mode}” ir aktīvs}zero{# režīmi ir aktīvi}one{# režīms ir aktīvs}other{# režīmi ir aktīvi}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Jūs netraucēs skaņas un vibrācija, izņemot signālus, atgādinājumus, pasākumus un zvanītājus, ko būsiet norādījis. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Jūs netraucēs skaņas un vibrācija, izņemot signālus. Jūs joprojām dzirdēsiet atskaņošanai izvēlētos vienumus, tostarp mūziku, videoklipus un spēles."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Pielāgot"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lēnā uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Logrīki bloķēšanas ekrānā"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Logrīks <xliff:g id="WIDGET_NAME">%1$s</xliff:g> pievienots bloķēšanas ekrānam"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pielāgot"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Nerādīt"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vai vēlaties sākt ierakstīšanu vai apraidi?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Viss ekrāns"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Viena lietotne"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Lietotnes kopīgošana vai ierakstīšana"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vai vēlaties sākt ierakstīšanu vai apraidi, izmantojot lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lietotnes kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Sākt"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vai kopīgot ekrānu ar lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kopīgot vienu lietotni"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kopīgot visu ekrānu"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kopīgojot visu ekrānu, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss ekrāna saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kopīgojot lietotni, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss kopīgotajā lietotnē parādītais vai atskaņotais saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kopīgot ekrānu"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> tika atspējota šī opcija"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vai sākt apraidi?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Apraides laikā Android var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lietotnes apraides laikā Android var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Sākt apraidi"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Vai apraidīt ekrānu?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Apraidīt vienu lietotni"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Apraidīt visu ekrānu"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Apraidot visu ekrānu, ir redzams viss ekrāna saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Apraidot lietotni, ir redzams viss attiecīgajā lietotnē rādītais vai atskaņotais. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Apraidīt ekrānu"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Vai sākt kopīgošanu?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kopīgošanas, ierakstīšanas vai apraides laikā Android var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Lietotnes kopīgošanas, ierakstīšanas vai apraides laikā Android var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Sākt"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Tālāk"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Pārslēdzot lietotnes, tiek pārtraukta kopīgošana."</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Tā vietā kopīgot šo lietotni"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Pārslēgties uz iepriekšējo"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pieejamība"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Īsinājumtaustiņi"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Meklēšanas saīsnes"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nav meklēšanas rezultātu"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sakļaušanas ikona"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Izvēršanas ikona"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vai"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Žests pāriešanai uz sākumu"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Darbību taustiņš"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gatavs"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Lieliski!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atpakaļ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Lai atgrieztos, ar trīs pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa.\n\nVarat arī izmantot šim nolūkam īsinājumtaustiņus: darbību taustiņu + Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pāreja uz sākuma ekrānu"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Lai jebkurā brīdī pārietu uz sākuma ekrānu, ar trim pirkstiem velciet augšup no ekrāna apakšdaļas."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Attēls ar skārienpaliktni, uz kura trīs pirksti kustas pa labi un pa kreisi"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ierīces ekrāns, kurā redzama animācija ar žestu pāriešanai atpakaļ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastatūras fona apgaismojums"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Līmenis numur %1$d, kopā ir %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Mājas kontrolierīces"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Lai pārietu uz sākuma ekrāna, ar trīs pirkstiem uz skārienpaliktņa velciet augšup."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Lai skatītu nesenās lietotnes, ar trīs pirkstiem uz skārienpaliktņa velciet augšup un turiet."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Lai skatītu visas savas lietotnes, tastatūrā nospiediet darbību taustiņu."</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Rediģēts"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lai skatītu, atbloķējiet"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Atgriešanās, izmantojot skārienpaliktni"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Ar trīs pirkstiem velciet pa kreisi vai pa labi. Lai apgūtu citus žestus, pieskarieties šeit."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Pāriešana uz sākuma ekrānu, izmantojot skārienpaliktni"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Ar trīs pirkstiem velciet augšup un turiet. Lai apgūtu citus žestus, pieskarieties šeit."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Visu lietotņu skatīšana, izmantojot tastatūru"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Jebkurā laikā varat nospiest darbību taustiņu. Lai apgūtu citus žestus, pieskarieties šeit."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Papildu aptumšošana tagad ir iekļauta spilgtuma joslā"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Tagad varat veikt ekrāna papildu aptumšošanu, vēl vairāk samazinot spilgtumu ekrāna augšdaļā.\n\nTas darbojas vislabāk, ja esat tumšā vietā."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Noņemt papildu aptumšošanas saīsni"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Papildu aptumšošanas saīsne ir noņemta. Lai samazinātu spilgtumu, izmantojiet parasto spilgtuma joslu."</string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 68f9a9da2985..3e09e4292742 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Снимач на екран"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Да се започне со снимање?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Додека снимате, Android има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Додека снимате апликација, Android има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Започни со снимање"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Снимај аудио"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Аудио од уредот"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук од вашиот уред, како на пр., музика, повици и мелодии"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Испрати"</string> <string name="cancel" msgid="1089011503403416730">"Откажи"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Лого на апликацијата"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потврди"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Обиди се повторно"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Допрете за да ја откажете проверката"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликнете за да спарите нов уред"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не можеше да се ажурира зададената вредност"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Зададени вредности"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Автоматски титлови"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Автоматски титлови"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Да се одблокира пристапот до микрофонот на уредот?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Да се одблокира пристапот до камерата на уредот?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Да се одблокира пристапот до камерата и микрофонот на уредот?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Поставки"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Исклучено"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Поставете"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Управувајте во поставките"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Нема активни режими}=1{Активен е {mode}}one{Активни се # режим}other{Активни се # режими}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Нема да ве вознемируваат звуци и вибрации, освен од аларми, потсетници, настани и повикувачи што ќе ги наведете. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Нема да ве вознемируваат звуци и вибрации, освен од аларми. Сѐ уште ќе слушате сѐ што ќе изберете да пуштите, како музика, видеа и игри."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Приспособи"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни бавно • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на заклучен екран"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Виџетот <xliff:g id="WIDGET_NAME">%1$s</xliff:g> е додаден на заклучениот екран"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Приспособете"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отфрли"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ќе има пристап до сите податоци што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова опфаќа податоци како лозинките, деталите за плаќање, фотографиите, пораките и аудиото што го пуштате."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Да почне снимање или емитување?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата што ја обезбедува функцијава ќе има пристап до сите податоци што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова вклучува податоци како лозинките, деталите за плаќање, фотографиите, пораките и аудиото што го пуштате."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Цел екран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Една апликација"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Споделување или снимање апликација"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Да почне снимање или емитување со <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Кога споделувате, снимате или емитувате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Кога споделувате, снимате или емитувате апликација, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Започни"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели вашиот екран со <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделете една апликација"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделете го целиот екран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Додека го споделувате целиот екран, сè на екранот е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Додека споделувате апликација, сѐ што се прикажува или пушта на таа апликација е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Сподели екран"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ја оневозможи опцијава"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Да се започне со емитување?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Кога емитувате, Android има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Додека емитувате апликација, Android има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки фотографии и аудио и видео."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Започни со емитување"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Да се емитува вашиот екран?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Емитувајте една апликација"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Емитувајте го целиот екран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Додека го емитувате целиот екран, може да се види сè што е на екранот. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Додека емитувате апликација, може да се види сѐ што се прикажува или пушта во таа апликација. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Емитувај го екранот"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Да се започне со споделување?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Кога споделувате, снимате или емитувате, Android има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Кога споделувате, снимате или емитувате апликација, Android има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Започни"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Следно"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Споделувањето се паузира кога се префрлате на друга апликација"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Наместо тоа, споделете ја апликацијава"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Враќање"</string> @@ -957,7 +969,7 @@ <string name="notification_channel_screenshot" msgid="7665814998932211997">"Слики од екранот"</string> <string name="notification_channel_instant" msgid="7556135423486752680">"Инстант апликации"</string> <string name="notification_channel_setup" msgid="7660580986090760350">"Поставување"</string> - <string name="notification_channel_storage" msgid="2720725707628094977">"Капацитет"</string> + <string name="notification_channel_storage" msgid="2720725707628094977">"Простор"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Совети"</string> <string name="notification_channel_accessibility" msgid="8956203986976245820">"Пристапност"</string> <string name="instant_apps" msgid="8337185853050247304">"Инстант апликации"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Пристапност"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Кратенки од тастатура"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Кратенки за пребарување"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Нема резултати од пребарување"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за собирање"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширување"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Движење за почетен екран"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Копче за дејство"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично сторено!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"За да се вратите назад, повлечете налево или надесно со три прста каде било на допирната подлога.\n\nЗа ова може да ја користите и кратенката од тастатурата Action + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Одете на почетниот екран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"За да одите на вашиот почетен екран кога сакате, повлечете нагоре со три прсти од дното на екранот."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Допирната подлога покажува три прста што се движат десно и лево"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екранот на уредот покажува анимација за движење назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d од %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за домот"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"За да одите на почетниот екран, повлечете нагоре со три прста на допирната подлога"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"За да ги видите скорешните апликации, повлечете нагоре и задржете со три прста на допирната подлога"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Притиснете го копчето за дејство на тастатурата за да ги видите сите апликации"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Редактирано"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Отклучете за приказ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Користете ја допирната подлога за да се вратите назад"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Повлечете налево или надесно со три прста. Допрете за да научите повеќе движења."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Користете ја допирната подлога за да одите на почетниот екран"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Повлечете нагоре и задржете со три прста. Допрете за да научите повеќе движења."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користете ја тастатурата за да ги видите сите апликации"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притиснете го копчето за дејство кога сакате. Допрете за да научите повеќе движења."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Отсега „Дополнително затемнување“ е дел од лентата за осветленост"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Отсега може да го затемнувате екранот дополнително со намалување на нивото на осветленост од горниот дел на екранот.\n\nОва функционира најдобро кога сте во темна средина."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Отстрани ја кратенката за „Дополнително затемнување“"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Кратенката за „Дополнително затемнување“ е отстранета. Користете ја стандардната лента за осветленост за да ја намалите осветленоста."</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 8711604d09c7..adf82359cec8 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"സ്ക്രീൻ റെക്കോർഡർ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"റെക്കോർഡ് ചെയ്യൽ ആരംഭിക്കണോ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"റെക്കോർഡ് ചെയ്യുമ്പോൾ, Android-ന് സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"നിങ്ങൾ ഒരു ആപ്പ് റെക്കോർഡ് ചെയ്യുമ്പോൾ, Android-ന് ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"റെക്കോർഡ് ചെയ്യൽ ആരംഭിക്കുക"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ഉപകരണത്തിന്റെ ഓഡിയോ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"സംഗീതം, കോളുകൾ, റിംഗ്ടോണുകൾ എന്നിവപോലെ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്നുള്ള ശബ്ദം"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"അയയ്ക്കുക"</string> <string name="cancel" msgid="1089011503403416730">"റദ്ദാക്കുക"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ആപ്പ് ലോഗോ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"സ്ഥിരീകരിക്കുക"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"വീണ്ടും ശ്രമിക്കുക"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കാൻ ടാപ്പ് ചെയ്യുക"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"പുതിയ ഉപകരണം ജോടിയാക്കാൻ ക്ലിക്ക് ചെയ്യുക"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"പ്രീസെറ്റ് അപ്ഡേറ്റ് ചെയ്യാനായില്ല"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"പ്രീസെറ്റ്"</string> - <string name="live_caption_title" msgid="8916875614623730005">"തത്സമയ ക്യാപ്ഷനുകൾ"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"തത്സമയ ക്യാപ്ഷനുകൾ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ഉപകരണ മൈക്രോഫോൺ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ഉപകരണ ക്യാമറ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ഉപകരണ ക്യാമറയോ മൈക്രോഫോണോ അൺബ്ലോക്ക് ചെയ്യണോ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ക്രമീകരണം"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ഓഫാണ്"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"സജ്ജീകരിക്കുക"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ക്രമീകരണത്തിൽ മാനേജ് ചെയ്യുക"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{സജീവ മോഡുകൾ ഒന്നുമില്ല}=1{{mode} സജീവമാണ്}other{# മോഡുകൾ സജീവമാണ്}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"നിങ്ങൾ സജ്ജീകരിച്ച അലാറങ്ങൾ, റിമൈൻഡറുകൾ, ഇവന്റുകൾ, കോളർമാർ എന്നിവയിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"അലാറങ്ങളിൽ നിന്നുള്ള ശബ്ദങ്ങളും വൈബ്രേഷനുകളുമൊഴികെ മറ്റൊന്നും നിങ്ങളെ ശല്യപ്പെടുത്തുകയില്ല. സംഗീതം, വീഡിയോകൾ, ഗെയിമുകൾ എന്നിവയുൾപ്പെടെ പ്ലേ ചെയ്യുന്നതെന്തും നിങ്ങൾക്ക് തുടർന്നും കേൾക്കാൻ കഴിയും."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ഇഷ്ടാനുസൃതമാക്കുക"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ലോക്ക് സ്ക്രീനിൽ വിജറ്റുകൾ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"ലോക്ക് സ്ക്രീനിലേക്ക് <xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ് ചേർത്തു"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ ഇടത്തോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ഇഷ്ടാനുസൃതമാക്കുക"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ഡിസ്മിസ് ചെയ്യുക"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആക്സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഓഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, പാസ്വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"റെക്കോർഡ് ചെയ്യൽ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യൽ ആരംഭിക്കണോ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും ഈ ഫംഗ്ഷൻ ലഭ്യമാക്കുന്ന സേവനത്തിന് ആക്സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഓഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, പാസ്വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"മുഴുവൻ സ്ക്രീൻ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ഒറ്റ ആപ്പ്"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ഒരു ആപ്പ് പങ്കിടുക അല്ലെങ്കിൽ റെക്കോർഡ് ചെയ്യുക"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ഉപയോഗിച്ച് റെക്കോർഡ് ചെയ്യൽ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യൽ ആരംഭിക്കണോ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആ ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ആരംഭിക്കുക"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"നിങ്ങളുടെ സ്ക്രീൻ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതുമായി പങ്കിടണോ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ഒരു ആപ്പ് പങ്കിടുക"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"സ്ക്രീൻ മുഴുവനായി പങ്കിടുക"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"നിങ്ങളുടെ സ്ക്രീൻ മുഴുവനായി പങ്കിടുമ്പോൾ, സ്ക്രീനിലെ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"നിങ്ങളുടെ ആപ്പ് പങ്കിടുമ്പോൾ, ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"സ്ക്രീൻ പങ്കിടുക"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഈ ഓപ്ഷൻ പ്രവർത്തനരഹിതമാക്കി"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"കാസ്റ്റ് ചെയ്യാൻ ആരംഭിക്കണോ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"നിങ്ങൾ കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"നിങ്ങൾ ഒരു ആപ്പ് കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"കാസ്റ്റ് ചെയ്യാൻ ആരംഭിക്കുക"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"നിങ്ങളുടെ സ്ക്രീൻ കാസ്റ്റ് ചെയ്യണോ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ഒരു ആപ്പ് കാസ്റ്റ് ചെയ്യുക"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"മുഴുവൻ സ്ക്രീനും കാസ്റ്റ് ചെയ്യുക"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"നിങ്ങളുടെ മുഴുവൻ സ്ക്രീനും കാസ്റ്റ് ചെയ്യുമ്പോൾ, സ്ക്രീനിലെ എല്ലാ കാര്യങ്ങളും ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധിക്കുക."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"നിങ്ങൾ ഒരു ആപ്പ് കാസ്റ്റ് ചെയ്യുമ്പോൾ, ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാ കാര്യങ്ങളും ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധിക്കുക."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"സ്ക്രീൻ കാസ്റ്റ് ചെയ്യുക"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"പങ്കിടൽ ആരംഭിക്കണോ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് ആ ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ആരംഭിക്കുക"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"അടുത്തത്"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"നിങ്ങൾ ആപ്പുകൾ മാറുമ്പോൾ പങ്കിടൽ താൽക്കാലികമായി നിർത്തും"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"പകരം ഈ ആപ്പ് പങ്കിടുക"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"മടങ്ങുക"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ഉപയോഗസഹായി"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"കീബോഡ് കുറുക്കുവഴികൾ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"തിരയൽ കുറുക്കുവഴികൾ"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"തിരയൽ ഫലങ്ങളൊന്നുമില്ല"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ചുരുക്കൽ ഐക്കൺ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"വികസിപ്പിക്കൽ ഐക്കൺ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"അല്ലെങ്കിൽ"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ഹോം ജെസ്ച്ചർ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ആക്ഷൻ കീ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"പൂർത്തിയായി"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"കൊള്ളാം!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"മടങ്ങുക"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"തിരികെ പോകാൻ, ടച്ച്പാഡിൽ എവിടെയെങ്കിലും മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക.\n\nഇതിന് Action + ESC കീബോഡ് കുറുക്കുവഴികളും നിങ്ങൾക്ക് ഉപയോഗിക്കാം."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ഹോമിലേക്ക് പോകൂ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ഏതുസമയത്തും ഹോം സ്ക്രീനിലേക്ക് പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യൂ."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"വലത്തേക്കും ഇടത്തേക്കും ചലിക്കുന്ന മൂന്ന് വിരലുകൾ കാണിക്കുന്ന ടച്ച്പാഡ്"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ബാക്ക് ജെസ്ച്ചറിനായി ആനിമേഷൻ കാണിക്കുന്ന ഉപകരണ സ്ക്രീൻ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"കീബോഡ് ബാക്ക്ലൈറ്റ്"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-ൽ %1$d-ാമത്തെ ലെവൽ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ഹോം കൺട്രോളുകൾ"</string> @@ -1400,12 +1425,18 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ഹോമിലേക്ക് പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ടച്ച്പാഡിൽ സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"എല്ലാ ആപ്പുകളും കാണാൻ, നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"മറച്ചത്"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"കാണാൻ, അൺലോക്ക് ചെയ്യുക"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"തിരികെ പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> - <string name="back_edu_notification_content" msgid="2497557451540954068">"മൂന്ന് വിരലുകളാൽ ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പുചെയ്യൂ. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="back_edu_notification_content" msgid="2497557451540954068">"മൂന്ന് വിരലുകൾ കൊണ്ട് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യൂ. കൂടുതൽ ജെസ്ച്ചറുകളറിയാൻ ടാപ്പ് ചെയ്യൂ."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ഹോമിലേക്ക് പോകാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> <string name="home_edu_notification_content" msgid="6631697734535766588">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="overview_edu_notification_title" msgid="1265824157319562406">"അടുത്തിടെ ഉപയോഗിച്ച ആപ്പുകൾ കാണാൻ നിങ്ങളുടെ ടച്ച്പാഡ് ഉപയോഗിക്കുക"</string> - <string name="overview_edu_notification_content" msgid="3578204677648432500">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="overview_edu_notification_content" msgid="3578204677648432500">"മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക. കൂടുതൽ ജെസ്ച്ചറുകളറിയാൻ ടാപ്പ് ചെയ്യൂ."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"എല്ലാ ആപ്പുകളും കാണാൻ നിങ്ങളുടെ കീബോർഡ് ഉപയോഗിക്കുക"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ഏതുസമയത്തും ആക്ഷൻ കീ അമർത്തുക. കൂടുതൽ ജെസ്ച്ചറുകൾ മനസ്സിലാക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"കൂടുതൽ ഡിം ചെയ്യൽ, ഇപ്പോൾ തെളിച്ചം ബാറിന്റെ ഭാഗമാണ്"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"മുകളിൽ നിന്ന് തെളിച്ചം കുറയ്ക്കുന്നതിലൂടെ നിങ്ങൾക്ക് ഇപ്പോൾ സ്ക്രീൻ കൂടുതൽ മങ്ങിക്കാൻ കഴിയും.\n\nനിങ്ങൾ ഇരുണ്ട മുറിയിലായിരിക്കുമ്പോൾ ഇത് മികച്ച രീതിയിൽ പ്രവർത്തിക്കുന്നു."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"കൂടുതൽ ഡിം ചെയ്യൽ കുറുക്കുവഴി നീക്കം ചെയ്യുക"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"കൂടുതൽ ഡിം ചെയ്യാനുള്ള കുറുക്കുവഴി നീക്കം ചെയ്തു. തെളിച്ചം കുറയ്ക്കാൻ, സാധാരണ \'തെളിച്ചം ബാർ\' ഉപയോഗിക്കുക."</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 95b4e3fe88c1..ae6651506aea 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Дэлгэцийн үйлдэл бичигч"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Бичиж эхлэх үү?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Таныг бичиж байх үед Android нь таны дэлгэцэд харуулсан эсвэл төхөөрөмжид тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Таныг апп бичиж байх үед Android тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Бичиж эхлэх"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Аудио бичих"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Төхөөрөмжийн аудио"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Хөгжим, дуудлага болон хонхны ая зэрэг таны төхөөрөмжийн дуу"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Илгээх"</string> <string name="cancel" msgid="1089011503403416730">"Цуцлах"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Аппын лого"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Баталгаажуулах"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Дахин оролдох"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Нотолгоог цуцлахын тулд товшино уу"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Шинэ төхөөрөмж хослуулахын тулд товшино уу"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Урьдчилсан тохируулгыг шинэчилж чадсангүй"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Урьдчилсан тохируулга"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Шууд тайлбар"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Шууд тайлбар"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Төхөөрөмжийн микрофоныг блокоос гаргах уу?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Төхөөрөмжийн камерыг блокоос гаргах уу?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Төхөөрөмжийн камер болон микрофоныг блокоос гаргах уу?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Тохиргоо"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Унтраалттай"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Тохируулах"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Тохиргоонд удирдах"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ямар ч идэвхтэй горим байхгүй}=1{{mode} идэвхтэй байна}other{# горим идэвхтэй байна}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Танд сэрүүлэг, сануулга, арга хэмжээ, таны сонгосон дуудлага илгээгчээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Танд сэрүүлгээс бусад дуу, чичиргээ саад болохгүй. Та хөгжим, видео, тоглоом зэрэг тоглуулахыг хүссэн бүх зүйлээ сонсох боломжтой хэвээр байна."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Тохируулах"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Удаан цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Түгжээтэй дэлгэц дээрх виджетүүд"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджетийг түгжээтэй дэлгэцэд нэмсэн"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Өөрчлөх"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Хаах"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь бичлэг хийх эсвэл дамжуулах үед таны дэлгэцэд харуулсан эсвэл таны төхөөрөмжөөс тоглуулсан бүх мэдээлэлд хандах эрхтэй байна. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, зураг, мессеж болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Энэ функцийг олгож буй үйлчилгээ нь бичлэг хийж эсвэл дамжуулж байх үед таны дэлгэцэд харуулсан эсвэл төхөөрөмжөөс тань тоглуулсан бүх мэдээлэлд хандах эрхтэй. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Бүтэн дэлгэц"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Нэг апп"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Апп хуваалцах эсвэл бичих"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-р бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Таныг хуваалцаж, бичиж эсвэл дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь таны дэлгэцэд харагдаж буй зүйл эсвэл төхөөрөмжид тань тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Таныг хуваалцаж, бичлэг хийж эсвэл апп дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио болон видео зэрэг бусад зүйлд болгоомжтой хандаарай."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Эхлүүлэх"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Дэлгэцээ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай хуваалцах уу?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Нэг апп хуваалцах"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дэлгэцийг бүтнээр нь хуваалцах"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Та дэлгэцээ бүхэлд нь хуваалцаж байхад дэлгэц дээр тань байгаа аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Таныг апп хуваалцаж байхад тухайн аппад харуулж эсвэл тоглуулж буй аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дэлгэцийг хуваалцах"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> энэ сонголтыг идэвхгүй болгосон"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Дамжуулж эхлэх үү?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Таныг дамжуулж байх үед Android таны дэлгэцэд харагдаж буй эсвэл төхөөрөмжид тань тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Таныг апп дамжуулж байх үед Android тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Дамжуулж эхлэх"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Дэлгэцээ дамжуулах уу?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Нэг апп дамжуулах"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Дэлгэцийг бүхэлд нь дамжуулах"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Та дэлгэцээ бүхэлд нь дамжуулах үед дэлгэц дээр тань байгаа аливаа зүйл харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Та апп дамжуулах үед тухайн аппад харуулж эсвэл тоглуулж буй аливаа зүйл харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Дэлгэц дамжуулах"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Хуваалцаж эхлэх үү?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Таныг хуваалцаж, бичлэг хийж эсвэл дамжуулж байх үед Android таны дэлгэцэд харуулсан эсвэл төхөөрөмжид тань тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Таныг хуваалцаж, бичлэг хийж эсвэл дамжуулж байх үед Android тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио болон видео зэрэг бусад зүйлд болгоомжтой хандаарай."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Эхлүүлэх"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Дараах"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Таныг аппууд сэлгэх үед хуваалцахыг түр зогсооно"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Оронд нь энэ аппыг хуваалцах"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Буцаж сэлгэх"</string> @@ -566,7 +578,7 @@ <string name="empty_shade_text" msgid="8935967157319717412">"Мэдэгдэл байхгүй"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Шинэ мэдэгдэл алга"</string> <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"Мэдэгдлийн хөргөлт асаалттай байна"</string> - <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Таныг хэт олон мэдэгдэл нэг дор авахад таны төхөөрөмжийн дууны түвшин болон сэрэмжлүүлэг/дохиог 2 хүртэлх минутын турш автоматаар багасгадаг."</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Таныг хэт олон мэдэгдэл нэг дор авахад таны төхөөрөмжийн дууны түвшин болон дохиог 2 хүртэлх минутын турш автоматаар багасгадаг."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Унтраах"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Хуучин мэдэгдлийг харах бол түгжээг тайл"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Энэ төхөөрөмжийг таны эцэг эх удирддаг"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Хандалт"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Товчлуурын шууд холбоос"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Товчлолууд хайх"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ямар ч хайлтын илэрц байхгүй"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Хураах дүрс тэмдэг"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Дэлгэх дүрс тэмдэг"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"эсвэл"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Үндсэн нүүрний зангаа"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тусгай товчлуур"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Болсон"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Үнэхээр сайн ажиллалаа!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Буцах"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Буцахын тулд мэдрэгч самбар дээр гурван хуруугаар хүссэн газраа зүүн эсвэл баруун тийш шударна уу.\n\nТа мөн үүнийг хийхэд Action + ESC товчлуурын шууд холбоосыг ашиглах боломжтой."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Үндсэн нүүр лүү очих"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Үндсэн нүүр лүүгээ хүссэн үедээ очихын тулд дэлгэцийнхээ доод талаас гурван хуруугаараа дээш шударна уу."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Гурван хуруу баруун болон зүүн тийш хөдөлж буйг харуулсан мэдрэгч самбар"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Буцах зангаанд зориулсан анимацийг харуулсан төхөөрөмжийн дэлгэц"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Гарын арын гэрэл"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-с %1$d-р түвшин"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Гэрийн удирдлага"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Нүүр хуудас руу очихын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шударна уу"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Саяхны аппуудыг харахын тулд мэдрэгч самбар дээр гурван хуруугаараа дээш шудраад, удаан дарна уу"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бүх аппаа харахын тулд гар дээр тань байх тусгай товчлуурыг дарна уу"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Хассан"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Харахын тулд түгжээг тайлна уу"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Буцахын тулд мэдрэгч самбараа ашиглах"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Гурван хуруугаараа зүүн эсвэл баруун тийш шударна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Нүүр хуудас руу очихын тулд мэдрэгч самбараа ашиглах"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Гурван хуруугаа ашиглан дээш шудраад, удаан дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бүх аппыг харахын тулд гараа ашиглах"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Тусгай товчлуурыг хүссэн үедээ дарна уу. Илүү олон зангаа сурахын тулд товшино уу."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Хэт бүүдгэр онцлог одоо гэрэлтүүлгийн самбарын нэг хэсэг боллоо"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Та одоо дэлгэцийнхээ дээд талаас гэрэлтүүлгийн түвшнийг бүр илүү багасгаснаар дэлгэцийг хэт бүүдгэр болгох боломжтой.\n\nЭнэ нь таныг харанхуй орчинд байхад хамгийн сайн ажилладаг."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Хэт бүүдгэр онцлогийн товчлолыг хасах"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Хэт бүүдгэр онцлогийн товчлолыг хассан. Гэрэлтүүлгээ багасгахын тулд энгийн гэрэлтүүлгийн самбарыг ашиглана уу."</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index e3510ad7c3c0..71d4307bfa7d 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रेकॉर्डर"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"रेकॉर्डिंग सुरू करायचे आहे का?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"तुम्ही रेकॉर्ड करत असताना, Android ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"तुम्ही एखादे ॲप रेकॉर्ड करत असताना, Android ला त्या ॲपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा ॲक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"रेकॉर्डिंग सुरू करा"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ऑडिओ रेकॉर्ड करा"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिव्हाइस ऑडिओ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तुमच्या डिव्हाइसवरील आवाज, जसे की संगीत, कॉल आणि रिंगटोन"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"पाठवा"</string> <string name="cancel" msgid="1089011503403416730">"रद्द करा"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"अॅप लोगो"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"कन्फर्म करा"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"पुन्हा प्रयत्न करा"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ऑथेंटिकेशन रद्द करण्यासाठी टॅप करा"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नवीन डिव्हाइस पेअर करण्यासाठी क्लिक करा"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट करता आले नाही"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"प्रीसेट"</string> - <string name="live_caption_title" msgid="8916875614623730005">"लाइव्ह कॅप्शन"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइव्ह कॅप्शन"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिव्हाइसचा मायक्रोफोन अनब्लॉक करायचा आहे का?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिव्हाइसचा कॅमेरा अनब्लॉक करायचा आहे का?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिव्हाइसचा कॅमेरा आणि मायक्रोफोन अनब्लॉक करायचा आहे का?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग्ज"</string> <string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद आहे"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"सेट करा"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"सेटिंग्जमध्ये व्यवस्थापित करा"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{कोणतेही अॅक्टिव्ह मोड नाहीत}=1{{mode} अॅक्टिव्ह आहे}other{# मोड अॅक्टिव्ह आहेत}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"अलार्म, रिमाइंडर, इव्हेंट आणि तुम्ही निश्चित केलेल्या कॉलर व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"अलार्म व्यतिरिक्त तुम्हाला कोणत्याही आवाज आणि कंपनांचा व्यत्त्यय आणला जाणार नाही. तरीही तुम्ही प्ले करायचे ठरवलेले कोणतेही संगीत, व्हिडिओ आणि गेमचे आवाज ऐकू शकतात."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"सानुकूलित करा"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • हळू चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लॉक स्क्रीनवरील विजेट"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट लॉक स्क्रीनवर जोडले आहे"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइझ करा"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"डिसमिस करा"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला तुमच्या स्क्रीनवर दाखवलेल्या अथवा तुमच्या डिव्हाइसवर प्ले केलेल्या सर्व माहितीचा अॅक्सेस असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले करत असलेला ऑडिओ यासारख्या माहितीचा समावेश आहे."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"रेकॉर्ड किंवा कास्ट करणे सुरू करायचे आहे का ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रेकॉर्ड किंवा कास्ट करत असताना, हे कार्य पुरवणाऱ्या सेवेला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या सर्व माहितीचा अॅक्सेस असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले करत असलेला ऑडिओ यासारख्या माहितीचा समावेश आहे."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"संपूर्ण स्क्रीन"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"एक अॅप"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"अॅप शेअर किंवा रेकॉर्ड करा"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> वापरून रेकॉर्ड किंवा कास्ट करणे सुरू करायचे आहे का?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"तुम्ही शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"तुम्ही एखादे अॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला त्या अॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"सुरुवात करा"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"तुमची स्क्रीन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सह शेअर करायची आहे का?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक अॅप शेअर करा"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"संपूर्ण स्क्रीन शेअर करा"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तुम्ही तुमची संपूर्ण स्क्रीन कास्ट करता, तेव्हा तुमच्या स्क्रीनवरील कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तुम्ही अॅप शेअर करता, तेव्हा त्या अॅपमध्ये दाखवल्या किंवा प्ले होणाऱ्या कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेअर करा"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा पर्याय बंद केला आहे"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"कास्ट करणे सुरू करायचे आहे का?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"तुम्ही कास्ट करत असताना, Android ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"तुम्ही एखादे अॅप कास्ट करत असताना, Android ला त्या अॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"कास्ट करणे सुरू करा"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"तुमची स्क्रीन कास्ट करायची आहे का?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"एक अॅप कास्ट करा"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"संपूर्ण स्क्रीन कास्ट करा"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"तुम्ही तुमची संपूर्ण स्क्रीन कास्ट करता, तेव्हा तुमच्या स्क्रीनवरील सर्व गोष्टी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"तुम्ही अॅप कास्ट करता, तेव्हा त्या अॅपमध्ये दाखवल्या किंवा प्ले होणाऱ्या सर्व गोष्टी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"स्क्रीन कास्ट करा"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"शेअर करणे सुरू करायचे आहे का?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"तुम्ही शेअर, रेकॉर्ड किंवा कास्ट करत असताना, Android ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"तुम्ही एखादे अॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, Android ला त्या अॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"सुरुवात करा"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"पुढील"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"तुम्ही ॲप्स स्विच करता, तेव्हा शेअरिंग थांबते"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"त्याऐवजी हे अॅप शेअर करा"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"परत स्विच करा"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"अॅक्सेसिबिलिटी"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"कीबोर्ड शॉर्टकट"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"शोधण्यासाठी शॉर्टकट"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"कोणतेही शोध परिणाम नाहीत"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"कोलॅप्स करा आयकन"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"विस्तार करा आयकन"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"किंवा"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेश्चर"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"अॅक्शन की"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"पूर्ण झाले"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"उत्तम कामगिरी!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"मागे जा"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तीन बोट उजवीकडे आणि डावीकडे हलताना दाखवणारे टचपॅड"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"मागील जेश्चरसाठी अॅनिमेशन दाखवणारी डिव्हाइस स्क्रीन"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"मागे जाण्यासाठी, तीन बोटांनी टचपॅडवर कुठेही डावीकडे किंवा उजवीकडे स्वाइप करा.\n\nतुम्ही यासाठी Action + ESC हा कीबोर्ड शॉर्टकटदेखील वापरू शकता."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"उत्तम कामगिरी!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"तुम्ही गो बॅक जेश्चर पूर्ण केले."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमवर जा"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"कधीही तुमच्या होम स्क्रीनवर जाण्यासाठी, तीन बोटांनी तुमच्या स्क्रीनच्या तळापासून स्वाइप करा."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"छान!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"तुम्ही गो होम जेश्चर पूर्ण केले आहे."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"अॅक्शन की"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"तुमची ॲप्स अॅक्सेस करण्यासाठी, तुमच्या कीबोर्डवरील अॅक्शन की प्रेस करा."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"अभिनंदन!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"तुम्ही अॅक्शन की जेश्चर पूर्ण केले आहे.\n\nकृती + / हे तुमच्याकडे उपलब्ध असलेले सर्व शॉर्टकट दाखवते."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d पैकी %1$d पातळी"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कंट्रोल"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"होमवर जाण्यासाठी, टचपॅडवर तीन बोटांनी वरती स्वाइप करा"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"अलीकडील ॲप्स पाहण्यासाठी, टचपॅडवर तीन बोटांनी वरती स्वाइप करा आणि धरून ठेवा"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"तुमची सर्व ॲप्स पाहण्यासाठी, तुमच्या कीबोर्डवरील अॅक्शन की प्रेस करा"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"रिडॅक्ट केलेले"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"पाहण्यासाठी अनलॉक करा"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"मागे जाण्यासाठी तुमचा टचपॅड वापरा"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"तीन बोटांनी डावीकडे किंवा उजवीकडे स्वाइप करा. आणखी जेश्चर जाणून घेण्यासाठी टॅप करा."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"होमवर जाण्यासाठी तुमचा टचपॅड वापरा"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"तीन बोटांनी वरती आणि खाली स्वाइप करा. आणखी जेश्चर जाणून घेण्यासाठी टॅप करा."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"सर्व ॲप्स पाहण्यासाठी तुमचा कीबोर्ड वापरा"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"अॅक्शन की कधीही प्रेस करा. आणखी जेश्चर जाणून घेण्यासाठी टॅप करा."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"आणखी डिम हे आता ब्राइटनेस बारचा भाग आहे"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"तुम्ही आता तुमच्या स्क्रीनच्या सर्वात वरून ब्राइटनेसची पातळी आणखी कमी करून स्क्रीनला आणखी डिम करू शकता.\n\nतुम्ही गडद वातावरणात असता, तेव्हा हे सर्वोत्तम कार्य करते."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"आणखी डिमचा शॉर्टकट काढून टाका"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"आणखी डिमचा शॉर्टकट काढून टाकला आहे. तुमचा ब्राइटनेस कमी करण्यासाठी, नेहमीचा ब्राइटनेस बार वापरा."</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 0e91cb467071..6ee9e0350e49 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Perakam Skrin"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Mulakan Rakaman?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Semasa anda merakam, Android boleh mengakses apa-apa sahaja yang kelihatan pada skrin atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati apabila memasukkan kata laluan, butiran pembayaran, mesej, foto, audio dan video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Semasa anda merakam apl, Android boleh mengakses apa-apa sahaja yang ditunjukkan atau dimainkan pada apl itu. Oleh hal yang demikian, berhati-hati ketika memasukkan kata laluan, butiran pembayaran, mesej, foto, audio dan video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Mulakan rakaman"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Rakam audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio peranti"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Bunyi daripada peranti anda, seperti muzik, panggilan dan nada dering"</string> @@ -138,7 +148,7 @@ <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Anda sedang berkongsi apl"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Hentikan perkongsian"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Menghantar skrin"</string> - <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Berhenti menghantar?"</string> + <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Hentikan penghantaran?"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Anda sedang menghantar seluruh skrin anda kepada <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Anda sedang menghantar seluruh skrin anda kepada peranti berdekatan"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Anda sedang menghantar <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> kepada <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Hantar"</string> <string name="cancel" msgid="1089011503403416730">"Batal"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo apl"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Sahkan"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Cuba lagi"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Ketik untuk membatalkan pengesahan"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik untuk menggandingkan peranti baharu"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat mengemaskinikan pratetapan"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Pratetapan"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Sari Kata Langsung"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sari Kata Langsung"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Nyahsekat mikrofon peranti?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Nyahsekat kamera peranti?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Nyahsekat kamera dan mikrofon peranti?"</string> @@ -475,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas dengan perlahan • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widget pada skrin kunci"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan pada skrin kunci"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ketepikan"</string> @@ -528,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan dapat mengakses semua maklumat yang kelihatan pada skrin anda atau yang dimainkan daripada peranti anda semasa merakam atau membuat penghantaran. Maklumat ini termasuk kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Mulakan rakaman atau penghantaran?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Perkhidmatan yang menyediakan fungsi ini boleh mengakses semua maklumat yang boleh dilihat pada skrin anda atau dimainkan daripada peranti anda semasa membuat rakaman atau penghantaran. Maklumat ini termasuk kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Seluruh skrin"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Satu apl"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Kongsi atau rakam apl"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Mulakan rakaman atau penghantaran dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Apabila anda membuat perkongsian, rakaman atau penghantaran, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> boleh mengakses apa-apa sahaja yang boleh dilihat pada skrin anda atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Apabila anda berkongsi, merakam atau menghantar apl, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> boleh mengakses apa-apa sahaja yang ditunjukan atau dimainkan pada apl tersebut. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Mula"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kongsi skrin anda dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kongsi satu apl"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kongsi seluruh skrin"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Apabila anda berkongsi seluruh skrin anda, apa-apa sahaja kandungan pada skrin anda boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Apabila anda berkongsi apl, apa-apa sahaja kandungan yang dipaparkan atau dimainkan pada apl boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kongsi skrin"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah melumpuhkan pilihan ini"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Mulakan penghantaran?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Apabila anda membuat penghantaran, Android boleh mengakses apa-apa sahaja yang kelihatan pada skrin atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati apabila memasukkan kata laluan, butiran pembayaran, mesej, foto, audio dan video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Apabila anda menghantar apl, Android boleh mengakses apa-apa sahaja yang ditunjukkan atau dimainkan pada apl itu. Oleh hal yang demikian, berhati-hati apabila memasukkan kata laluan, butiran pembayaran, mesej, foto, audio dan video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Mulakan penghantaran"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Hantar skrin anda?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Hantar satu apl"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Hantar keseluruhan skrin"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Apabila anda menghantar seluruh skrin anda, apa-apa sahaja kandungan pada skrin anda boleh dilihat. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Apabila anda menghantar apl, apa-apa sahaja kandungan yang dipaparkan atau dimainkan pada apl itu boleh dilihat. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Hantar skrin"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Mulakan perkongsian?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Apabila anda membuat perkongsian, rakaman atau penghantaran, Android boleh mengakses apa-apa sahaja yang boleh dilihat pada skrin anda atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Apabila anda berkongsi, merakam atau menghantar apl, Android boleh mengakses apa-apa sahaja yang ditunjukan atau dimainkan pada apl tersebut. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Mula"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Seterusnya"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Perkongsian dijeda apabila anda menukar apl"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Sebaliknya kongsi apl ini"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Tukar kembali"</string> @@ -1373,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Kebolehaksesan"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Pintasan papan kekunci"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Pintasan carian"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Tiada hasil carian"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kuncupkan ikon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kembangkan ikon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string> @@ -1380,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gerak isyarat pergi ke laman utama"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kekunci tindakan"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Syabas!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Untuk kembali, leret ke kiri atau ke kanan menggunakan tiga jari di mana-mana sahaja pada pad sentuh.\n\nAnda juga boleh menggunakan pintasan papan kekunci Action + ESC untuk kembali."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Akses laman utama"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Untuk mengakses skrin utama anda pada bila-bila masa, leret ke atas menggunakan tiga jari daripada bahagian bawah skrin anda."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Pad sentuh menunjukkan tiga jari bergerak ke kanan dan kiri"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrin peranti menunjukkan animasi untuk gerak isyarat kembali"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tahap %1$d daripada %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kawalan Rumah"</string> @@ -1397,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Untuk mengakses laman utama, leret ke atas dengan tiga jari pada pad sentuh"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Untuk melihat apl terbaharu, leret ke atas dan tahan dengan tiga jari pada pad sentuh"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua apl anda, tekan kekunci tindakan pada papan kekunci anda"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Disunting"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Buka kunci untuk melihat"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Gunakan pad sentuh anda untuk kembali"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Leret ke kiri atau ke kanan dengan tiga jari. Ketik dan ketahui lebih lanjut tentang gerak isyarat."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Gunakan pad sentuh untuk mengakses laman utama"</string> @@ -1405,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Leret ke atas, tahan dengan tiga jari. Ketik untuk mengetahui lebih lanjut tentang gerak isyarat."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan papan kekunci anda untuk melihat semua apl"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan kekunci tindakan pada bila-bila masa. Ketik dan ketahui lebih lanjut tentang gerak isyarat."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Kini ciri amat malap merupakan sebahagian daripada bar kecerahan"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Kini anda boleh menjadikan skrin amat malap dengan merendahkan tahap kecerahan lebih jauh daripada bahagian atas skrin anda.\n\nCiri ini berfungsi paling baik apabila anda berada dalam persekitaran yang gelap."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Alih keluar pintasan amat malap"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Pintasan amat malap dialih keluar. Untuk mengurangkan kecerahan anda, gunakan bar kecerahan biasa."</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index d7b20ef089ce..3cddbda1529f 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ဖန်သားပြင်ရိုက်ကူးစက်"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ရုပ်သံဖမ်းခြင်း စတင်မလား။"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ရုပ်သံဖမ်းနေစဉ် Android သည် သင့်ဖန်သားပြင်တွင် မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"အက်ပ်တစ်ခုကို ရုပ်သံဖမ်းနေစဉ် Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ရုပ်သံ စဖမ်းရန်"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"အသံဖမ်းရန်"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"စက်ပစ္စည်းအသံ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"သီချင်း၊ ဖုန်းခေါ်ဆိုမှုနှင့် ဖုန်းမြည်သံကဲ့သို့ သင့်စက်ပစ္စည်းမှ အသံ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ပို့ရန်"</string> <string name="cancel" msgid="1089011503403416730">"မလုပ်တော့"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"အက်ပ်လိုဂို"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"အတည်ပြုရန်"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ထပ်စမ်းကြည့်ရန်"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်ရန် တို့ပါ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"စက်အသစ် တွဲချိတ်ရန် နှိပ်ပါ"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"အသင့်သုံးကို အပ်ဒိတ်လုပ်၍မရပါ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ကြိုတင်သတ်မှတ်ချက်"</string> - <string name="live_caption_title" msgid="8916875614623730005">"တိုက်ရိုက်စာတန်း"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"တိုက်ရိုက်စာတန်း"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"စက်၏မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"စက်၏ကင်မရာကို ပြန်ဖွင့်မလား။"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"စက်၏ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပြန်ဖွင့်မလား။"</string> @@ -475,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"လော့ခ်မျက်နှာပြင်ရှိ ဝိဂျက်များ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်ကို လော့ခ်မျက်နှာပြင်တွင် ထည့်ထားသည်"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"စိတ်ကြိုက်လုပ်ရန်"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ပယ်ရန်"</string> @@ -528,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် ရုပ်သံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ရုပ်သံဖမ်းခြင်း (သို့) ကာစ်လုပ်ခြင်း စမလား။"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် ရုပ်သံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ဖန်သားပြင်တစ်ခုလုံး"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"အက်ပ်တစ်ခုတွင်"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"အက်ပ် မျှဝေခြင်း (သို့) ရိုက်ကူးခြင်း"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် ရုပ်သံဖမ်းခြင်း သို့မဟုတ် ကာစ်လုပ်ခြင်း စတင်မလား။"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"အက်ပ်တစ်ခုဖြင့် မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"စတင်ရန်"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"သင့်စခရင်ကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် မျှဝေမလား။"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"အက်ပ်တစ်ခု မျှဝေရန်"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"စခရင်တစ်ခုလုံး မျှဝေရန်"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"သင့်စခရင်တစ်ခုလုံးကို မျှဝေနေချိန်တွင် စခရင်ပေါ်ရှိ အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"အက်ပ်ကို မျှဝေနေချိန်တွင် ယင်းအက်ပ်တွင် ပြထားသော (သို့) ဖွင့်ထားသော အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"စခရင် မျှဝေရန်"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် ဤရွေးစရာကို ပိတ်ထားသည်"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ကာစ်လုပ်ခြင်း စမလား။"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ကာစ်လုပ်သည့်အခါ Android သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"အက်ပ်တစ်ခုကို ကာစ်လုပ်သည့်အခါ Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ကာစ်လုပ်ခြင်း စရန်"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"သင့်ဖန်သားပြင်ကို ကာစ်လုပ်မလား။"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"အက်ပ်တစ်ခုကို ကာစ်လုပ်ရန်"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"ဖန်သားပြင်တစ်ခုလုံးကို ကာစ်လုပ်ရန်"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"သင့်ဖန်သားပြင်တစ်ခုလုံးကို ကာစ်လုပ်သည့်အခါ ဖန်သားပြင်ပေါ်ရှိ အရာအားလုံးကို မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"အက်ပ်တစ်ခုကို ကာစ်လုပ်သည့်အခါ ယင်းအက်ပ်တွင် ပြထားသော (သို့) ဖွင့်ထားသော အရာအားလုံးကို မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"စခရင် ကာစ်လုပ်ရန်"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"စတင်မျှဝေမလား။"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ Android သည် သင့်ဖန်သားပြင်တွင် မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"အက်ပ်တစ်ခုဖြင့် မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့အရာများကို ဂရုစိုက်ပါ။"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"စတင်ရန်"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ရှေ့သို့"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"အက်ပ်ပြောင်းချိန်တွင် မျှဝေခြင်းကို ခဏရပ်သည်"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"၎င်းအစား ဤအက်ပ်ကို မျှဝေရန်"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ပြန်ပြောင်းရန်"</string> @@ -1373,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"အများသုံးနိုင်မှု"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"လက်ကွက်ဖြတ်လမ်းများ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ရှာဖွေစာလုံး ဖြတ်လမ်း"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ရှာဖွေမှုရလဒ် မရှိပါ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"လျှော့ပြရန် သင်္ကေတ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ပိုပြရန် သင်္ကေတ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"သို့မဟုတ်"</string> @@ -1380,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ပင်မစာမျက်နှာ လက်ဟန်"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"လုပ်ဆောင်ချက်ကီး"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ပြီးပြီ"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"တော်ပါပေသည်။"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ပြန်သွားရန်"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"နောက်ပြန်သွားရန် တာ့ချ်ပက်ပေါ်ရှိ မည်သည့်နေရာ၌မဆို လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။\n\n၎င်းအတွက် လက်ကွက်ဖြတ်လမ်း Action + ESC ကိုလည်း သုံးနိုင်သည်။"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ပင်မစာမျက်နှာသို့ သွားရန်"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ပင်မစာမျက်နှာသို့ အချိန်မရွေးသွားရန် စခရင်အောက်ခြေမှ အပေါ်သို့ လက်သုံးချောင်းဖြင့် ပွတ်ဆွဲပါ။"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"တာ့ချ်ပက်တွင် ဘယ်ညာရွှေ့နေသော လက်သုံးချောင်းကို ပြထားသည်"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"စက်စခရင်တွင် နောက်သို့လက်ဟန်အတွက် လှုပ်ရှားသက်ဝင်ပုံကို ပြထားသည်"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ကီးဘုတ်နောက်မီး"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"အဆင့် %2$d အနက် %1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"အိမ်ထိန်းချုပ်မှုများ"</string> @@ -1397,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ပင်မစာမျက်နှာသို့ သွားရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"လတ်တလောအက်ပ်များကို ကြည့်ရန် တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"သင့်အက်ပ်အားလုံးကြည့်ရန် ကီးဘုတ်ပေါ်ရှိ လုပ်ဆောင်ချက်ကီးကို နှိပ်ပါ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"အစားထိုးထားသည်"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ကြည့်ရန် ဖွင့်ပါ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"နောက်ပြန်သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ပင်မစာမျက်နှာသို့ သွားရန် သင့်တာ့ချ်ပက်ကို သုံးပါ"</string> @@ -1405,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"အက်ပ်အားလုံးကြည့်ရန် သင့်ကီးဘုတ်ကို သုံးပါ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"လုပ်ဆောင်ချက်ကီးကို အချိန်မရွေးနှိပ်ပါ။ လက်ဟန်များ ပိုမိုလေ့လာရန် တို့ပါ။"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ပိုမှိန်ခြင်းသည် တောက်ပမှုဘားတွင် ပါဝင်လာပြီ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"သင့်စခရင်ထိပ်ဆုံး၌ပင် တောက်ပမှုအဆင့်လျှော့ချခြင်းဖြင့် စခရင်ကို ပိုမှိန်အောင် လုပ်နိုင်ပါပြီ။\n\nသင်သည် မှောင်သောပတ်ဝန်းကျင်၌ရှိချိန် ၎င်းက အကောင်းဆုံးအလုပ်လုပ်သည်။"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ပိုမှိန်ခြင်း ဖြတ်လမ်း ဖယ်ရှားရန်"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ပိုမှိန်ခြင်း ဖြတ်လမ်းကို ဖယ်ရှားလိုက်ပြီ။ တောက်ပမှုလျှော့ရန် ပုံမှန် တောက်ပမှုဘားကို အသုံးပြုပါ။"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 07b979f9a223..ce157605e701 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Skjermopptak"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Vil du begynne å ta opp?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Når du tar opp noe, har Android tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Når du tar opp en app, har Android tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Begynn å ta opp"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Spill inn lyd"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Enhetslyd"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Lyd fra enheten, f.eks. musikk, samtaler og ringelyder"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Send"</string> <string name="cancel" msgid="1089011503403416730">"Avbryt"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Applogo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekreft"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Prøv på nytt"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Trykk for å avbryte autentiseringen"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klikk for å koble til en ny enhet"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kunne ikke oppdatere forhåndsinnstillingen"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forhåndsinnstilling"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Direkteteksting"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Direkteteksting"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vil du oppheve blokkeringen av enhetsmikrofonen?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vil du oppheve blokkeringen av enhetskameraet?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vil du oppheve blokkeringen av enhetskameraet og -mikrofonen?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Innstillinger"</string> <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfigurer"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrer i innstillingene"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ingen aktive moduser}=1{{mode} er aktiv}other{# moduser er aktive}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer, påminnelser, aktiviteter og oppringere du angir. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir ikke forstyrret av lyder og vibrasjoner, med unntak av alarmer. Du kan fremdeles høre alt du velger å spille av, for eksempel musikk, videoer og spill."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Tilpass"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Moduler på låseskjermen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modulen er lagt til på låseskjermen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpass"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Lukk"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får tilgang til all informasjon som vises på skjermen eller spilles av fra enheten når du tar opp eller caster noe. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vil du begynne å ta opp eller caste?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten som leverer denne funksjonen, får tilgang til all informasjon som vises på skjermen eller spilles av fra enheten mens du tar opp eller caster noe. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Hele skjermen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Én app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Del eller ta opp en app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vil du begynne å ta opp eller caste med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Når du deler, tar opp eller caster noe, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Når du deler, tar opp eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Begynn"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele skjermen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skjermen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skjermen, er alt på skjermen synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt som vises eller spilles av i appen, synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skjermen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har deaktivert dette alternativet"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vil du begynne å caste?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Når du caster, har Android tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Når du caster en app, har Android tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Begynn å caste"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Vil du caste skjermen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Cast én app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Cast hele skjermen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Når du caster hele skjermen, er alt på skjermen synlig. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Når du caster en app, er alt som vises eller spilles av i appen, synlig. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Cast skjermen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Vil du begynne å dele?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Når du deler, tar opp eller caster noe, har Android tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Når du deler, tar opp eller caster en app, har Android tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Begynn"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Neste"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Delingen settes på pause når du bytter app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Del denne appen i stedet"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Bytt tilbake"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Tilgjengelighet"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Hurtigtaster"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Snarveier til søk"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ingen søkeresultater"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Skjul-ikon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vis-ikon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Startskjermbevegelse"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Ferdig"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbet!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbake"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"For å gå tilbake, sveip mot høyre eller venstre med tre fingre hvor som helst på styreflaten.\n\nDu kan også gjøre dette med hurtigtasten Action + Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startsiden"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"For å gå til startskjermen, sveip opp med tre fingre fra bunnen av skjermen når som helst."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"En styreflate med tre fingre som beveger seg til høyre og venstre"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Enhetsskjerm med animasjonen for tilbakebevegelse"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrunnslys for tastatur"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemkontroller"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"For å gå til startsiden, sveip opp med tre fingre på styreflaten"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"For å se nylige apper, sveip opp og hold med tre fingre på styreflaten"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"For å se alle appene dine, trykk på handlingstasten på tastaturet"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Fjernet"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås opp for å se"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Bruk styreflaten for å gå tilbake"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Sveip til venstre eller høyre med tre fingre. Trykk for å lære flere bevegelser."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Bruk styreflaten for å gå til startsiden"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Sveip opp og hold med tre fingre. Trykk for å lære flere bevegelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bruk tastaturet for å se alle apper"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Trykk på handlingstasten når som helst. Trykk for å lære flere bevegelser."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Nå er ekstra dimmet en del av lysstyrkeraden"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nå kan du gjøre skjermen ekstra dimmet ved å redusere lysstyrkenivået enda mer fra toppen av skjermen.\n\nDette fungerer best i mørke omgivelser."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjern hurtigtasten for ekstra dimmet"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Hurtigtasten for ekstra dimmet er fjernet. For å redusere lysstyrken kan du bruke den vanlige lysstyrkeraden."</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 67843fd719d8..e615a04a57a0 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"स्क्रिन रेकर्डर"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"रेकर्ड गर्न थाल्ने हो?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"तपाईंले रेकर्ड गर्दै गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"तपाईंले कुनै एप रेकर्ड गर्दै गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"रेकर्ड गर्न थाल्नुहोस्"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"अडियो रेकर्ड गर्नुहोस्"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"डिभाइसको अडियो"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"तपाईंको डिभाइसका सङ्गीत, कल र रिङटोन जस्ता साउन्ड"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"पठाउनुहोस्"</string> <string name="cancel" msgid="1089011503403416730">"रद्द गर्नुहोस्"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"एपको लोगो"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"पुष्टि गर्नुहोस्"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"फेरि प्रयास गर्नुहोस्"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"प्रमाणीकरण रद्द गर्न ट्याप गर्नुहोस्"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नयाँ डिभाइसमा कनेक्ट गर्न क्लिक गर्नुहोस्"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रिसेट अपडेट गर्न सकिएन"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"पूर्वनिर्धारित"</string> - <string name="live_caption_title" msgid="8916875614623730005">"लाइभ क्याप्सन"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइभ क्याप्सन"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"डिभाइसको माइक्रोफोन अनब्लक गर्ने हो?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"डिभाइसको क्यामेरा अनब्लक गर्ने हो?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"डिभाइसको क्यामेरा र माइक्रोफोन अनब्लक गर्ने हो?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिङ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"अफ छ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"सेटअप गर्नुहोस्"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"सेटिङमा गई व्यवस्थापन गर्नुहोस्"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{कुनै पनि मोड सक्रिय छैन}=1{{mode} सक्रिय छ}other{# वटा मोड सक्रिय छन्}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"तपाईंलाई अलार्म, रिमाइन्डर, कार्यक्रम र तपाईंले निर्दिष्ट गर्नुभएका कलरहरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"तपाईंलाई अलार्महरू बाहेकका ध्वनि र कम्पनहरूले बाधा पुऱ्याउने छैनन्। तपाईंले अझै सङ्गीत, भिडियो र खेलहरू लगायत आफूले प्ले गर्न छनौट गरेका जुनसुकै कुरा सुन्न सक्नुहुनेछ।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">" कस्टम बनाउनुहोस्"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • बिस्तारै चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा पूरै चार्ज हुन्छ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"लक स्क्रिनमा भएका विजेटहरू"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"लक स्क्रिनमा <xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट हालिएको छ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइज गर्नुहोस्"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारेज गर्नुहोस्"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले रेकर्ड वा कास्ट गर्दै गर्दा तपाईंको स्क्रिनमा देखिने सबै जानकारी अथवा तपाईंको डिभाइसबाट प्ले गरिने सबै सामग्री हेर्न तथा प्रयोग गर्न सक्छ। यसअन्तर्गत पासवर्ड, भुक्तानीसम्बन्धी विवरण, फोटो, म्यासेज र तपाईंले प्ले गर्ने अडियो जस्ता कुराहरू समावेश हुन्छन्।"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"रेकर्ड वा कास्ट गर्न थाल्ने हो?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"यो फङ्सन प्रदान गर्ने सेवाले रेकर्ड वा कास्ट गर्दै गर्दा तपाईंको स्क्रिनमा देखिने सबै जानकारी अथवा तपाईंको डिभाइसबाट प्ले गरिने सबै सामग्री हेर्न तथा प्रयोग गर्न सक्छ। यसअन्तर्गत पासवर्ड, भुक्तानीसम्बन्धी विवरण, फोटो, म्यासेज र तपाईंले प्ले गर्ने अडियो जस्ता कुराहरू समावेश हुन्छन्।"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"पूरा स्क्रिन"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"एकल एप"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"कुनै एप सेयर वा रेकर्ड गर्नुहोस्"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मार्फत रेकर्ड गर्न वा कास्ट गर्न थाल्ने हो?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"तपाईंले कुनै एप सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"सुरु गर्नुहोस्"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"स्क्रिन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सँग सेयर गर्ने हो?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एउटा एप सेयर गर्नुहोस्"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरै स्क्रिन सेयर गर्नुहोस्"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तपाईंले पूरै स्क्रिन सेयर गरिरहेका बेला तपाईंको स्क्रिनमा देखिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तपाईंले यो एप सेयर गरिरहेका बेला यो एपमा देखाइने वा प्ले गरिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रिन सेयर गर्नुहोस्"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले यो विकल्प अफ गर्नुभएको छ"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"कास्ट गर्न थाल्ने हो?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"तपाईंले कास्ट गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"तपाईंले कुनै एप कास्ट गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"कास्ट गर्न थाल्नुहोस्"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"स्क्रिन कास्ट गर्ने हो?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"एउटा एप कास्ट गर्नुहोस्"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"पूरै स्क्रिन कास्ट गर्नुहोस्"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"तपाईंले पूरै स्क्रिन कास्ट गरिरहेका बेला तपाईंको स्क्रिनमा देखिने सबै सामग्री अर्को स्क्रिनमा पनि देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"तपाईंले यो एप कास्ट गरिरहेका बेला यो एपमा देखाइने वा प्ले गरिने सबै सामग्री अर्को स्क्रिनमा पनि देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"स्क्रिन कास्ट गर्नुहोस्"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"सेयर गर्न थाल्ने हो?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"तपाईंले कुनै एप सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"सुरु गर्नुहोस्"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"अर्को"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"तपाईंले एपहरू बदल्दा सेयर गर्ने प्रक्रिया पज हुन्छ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"यसको साटो यो एप सेयर गर्नुहोस्"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"पछाडि जानुहोस्"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"सर्वसुलभता"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"किबोर्डका सर्टकटहरू"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"खोजका सर्टकटहरू"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"कुनै पनि खोज परिणाम भेटिएन"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\"कोल्याप्स गर्नुहोस्\" आइकन"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\"एक्स्पान्ड गर्नुहोस्\" आइकन"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"वा"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेस्चर"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"एक्सन की"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"सम्पन्न भयो"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"अद्भुत!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"पछाडि जानुहोस्"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"पछाडि जान तीन वटा औँलाले टचप्याडमा कतै छोएर बायाँ वा दायाँतिर स्वाइप गर्नुहोस्।\n\nतपाईं यसका लागि किबोर्डको सर्टकट \"Action + ESC\" पनि प्रयोग गर्न सक्नुहुन्छ।"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमपेजमा जानुहोस्"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"जुनसुकै बेला आफ्नो होम स्क्रिनमा जान स्क्रिनको फेदबाट तीन वटा औँलाले माथितिर स्वाइप गर्नुहोस्।"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"तिन वटा औँला दायाँ र बायाँ सारेको देखाइएको टचप्याड"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"पछाडि जाने जेस्चरको एनिमेसन देखाइएको डिभाइसको स्क्रिन"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"किबोर्ड ब्याकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d मध्ये %1$d औँ स्तर"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कन्ट्रोलहरू"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"होममा जान तिन वटा औँलाले टचप्याडमा माथितिर स्वाइप गर्नुहोस्"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"आफूले हालसालै चलाएका एपहरू हेर्न तिन वटा औँलाले टचप्याडमा माथितिर स्वाइप गर्नुहोस् र होल्ड गर्नुहोस्"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"आफ्ना सबै एपहरू हेर्न आफ्नो किबोर्डमा भएको एक्सन की थिच्नुहोस्"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"जानकारी लुकाउन सम्पादन गरिएको"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"हेर्नका लागि अनलक गर्नुहोस्"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"पछाडि जान आफ्नो टचप्याड प्रयोग गर्नुहोस्"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"तिन वटा औँला प्रयोग गरी बायाँ वा दायाँतिर स्वाइप गर्नुहोस्। थप जेस्चर प्रयोग गर्ने तरिका सिक्न ट्याप गर्नुहोस्।"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"होममा जान आफ्नो टचप्याड प्रयोग गर्नुहोस्"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"तिन वटा औँला प्रयोग गरी माथितिर स्वाइप गर्नुहोस् र होल्ड गर्नुहोस्। थप जेस्चर प्रयोग गर्ने तरिका सिक्न ट्याप गर्नुहोस्।"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"सबै एपहरू हेर्न आफ्नो किबोर्ड प्रयोग गर्नुहोस्"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"जुनसुकै बेला एक्सन की थिच्नुहोस्। थप जेस्चर प्रयोग गर्ने तरिका सिक्न ट्याप गर्नुहोस्।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"\"अझै मधुरो\" सुविधा अब ब्राइटनेस बारमा समावेश गरिएको छ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"तपाईं अब आफ्नो स्क्रिनको सिरानबाट चमकको स्तर घटाएर आफ्नो स्क्रिन अझै मधुरो बनाउन सक्नुहुन्छ।\n\nतपाईं अँध्यारो ठाउँमा भएका बेला यो सुविधाले अझ राम्रोसँग काम गर्छ।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\"अझै मधुरो\" सर्टकट हटाउनुहोस्"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\"अझै मधुरो\" सर्टकट हटाइएको छ। स्क्रिनको चमक घटाउन \"रेगुलर ब्राइटनेस बार\" प्रयोग गर्नुहोस्।"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index d259a3d74154..dc037103749f 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Schermopname"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Opname starten?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Terwijl je aan het opnemen bent, heeft Android toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Terwijl je een app aan het opnemen bent, heeft Android toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Opname starten"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio opnemen"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio van apparaat"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Geluid van je apparaat, zoals muziek, gesprekken en ringtones"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Verzenden"</string> <string name="cancel" msgid="1089011503403416730">"Annuleren"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"App-logo"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bevestigen"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Opnieuw proberen"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tik om de verificatie te annuleren"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klik om nieuw apparaat te koppelen"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kan voorinstelling niet updaten"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voorinstelling"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live ondertiteling"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live ondertiteling"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Microfoon van apparaat niet meer blokkeren?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Apparaatcamera niet meer blokkeren?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Blokkeren van apparaatcamera en -microfoon opheffen?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellingen"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Uit"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Instellen"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Beheren via instellingen"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Geen actieve modi}=1{{mode} is actief}other{# modi zijn actief}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers, herinneringen, afspraken en specifieke bellers die je selecteert. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Je wordt niet gestoord door geluiden en trillingen, behalve bij wekkers. Je kunt nog steeds alles horen wat je wilt afspelen, waaronder muziek, video\'s en games."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Aanpassen"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Langzaam opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets op het vergrendelscherm"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> toegevoegd aan vergrendelscherm"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Aanpassen"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Sluiten"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> krijgt toegang tot alle informatie die zichtbaar is op je scherm of die wordt afgespeeld vanaf je apparaat tijdens het opnemen of casten. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Opnemen of casten starten?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"De service die deze functie levert, krijgt tijdens het opnemen of casten toegang tot alle informatie die zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Volledig scherm"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Eén app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"App delen of opnemen"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Opnemen of casten starten met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Als je deelt, opneemt of cast, heeft <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Als je deelt, opneemt of cast, heeft <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Starten"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Je scherm delen met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eén app delen"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Hele scherm delen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Als je het hele scherm deelt, is alles op je scherm zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Als je een app deelt, is alles dat wordt getoond of afgespeeld in die app zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Scherm delen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Voor <xliff:g id="APP_NAME">%1$s</xliff:g> staat deze optie uit"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Casten starten?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Als je cast, heeft Android toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Als je een app cast, heeft Android toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Casten starten"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Je scherm casten?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Eén app casten"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Hele scherm casten"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Als je het hele scherm cast, is alles op je scherm zichtbaar. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Als je een app cast, is alles zichtbaar dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Scherm casten"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Delen starten?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Als je deelt, opneemt of cast, heeft Android toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Als je deelt, opneemt of cast, heeft Android toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Starten"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Volgende"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Delen wordt onderbroken als je schakelt tussen apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"In plaats daarvan deze app delen"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Terugschakelen"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Toegankelijkheid"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Sneltoetsen"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Snelkoppelingen voor zoekopdrachten"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Geen zoekresultaten"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icoon voor samenvouwen"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icoon voor uitvouwen"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gebaar voor startscherm"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Actietoets"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Goed werk!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Terug"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad met 3 vingers die naar rechts en links bewegen"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Apparaatscherm met animatie voor teruggebaar"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Als je wilt teruggaan, swipe je met 3 vingers naar links of rechts op de touchpad.\n\nJe kunt hiervoor ook de sneltoets Actie + ESC gebruiken."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Goed bezig!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Je weet nu hoe je het gebaar voor terug maakt."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Naar startscherm"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Swipe met 3 vingers omhoog vanaf de onderkant van het scherm om naar het startscherm te gaan."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Mooi zo!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Je weet nu hoe je het gebaar Naar startscherm maakt."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Actietoets"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Als je toegang tot je apps wilt krijgen, druk je op de actietoets op je toetsenbord."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gefeliciteerd!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Je hebt het gebaar voor de actietoets uitgevoerd.\n\nActie + / toont alle beschikbare sneltoetsen."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Achtergrondverlichting van toetsenbord"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d van %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Bediening voor in huis"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Als je naar het startscherm wilt gaan, swipe je met 3 vingers omhoog op de touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Als je recente apps wilt bekijken, swipe je met 3 vingers omhoog op de touchpad en houd je vast"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Als je alle apps wilt bekijken, druk je op de actietoets op je toetsenbord"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Verborgen"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ontgrendelen om te bekijken"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Je touchpad gebruiken om terug te gaan"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe met 3 vingers naar links of rechts. Tik voor meer gebaren."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Je touchpad gebruiken om naar het startscherm te gaan"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe met 3 vingers omhoog en houd vast. Tik voor meer gebaren."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Je toetsenbord gebruiken om alle apps te bekijken"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk op de actietoets wanneer je wilt. Tik voor meer gebaren."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dimmen maakt nu deel uit van de helderheidsbalk"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Je kunt het scherm nu extra dimmen door het helderheidsniveau nog verder te verlagen vanaf de bovenkant van het scherm.\n\nDit werkt het beste als je in een donkere omgeving bent."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Snelkoppeling voor extra dimmen verwijderen"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Snelkoppeling voor extra dimmen verwijderd. Als je de helderheid wilt verlagen, gebruik je de gewone helderheidsbalk."</string> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 11681c939e7a..eb87ef2b70eb 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ସ୍କ୍ରିନ ରେକର୍ଡର"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରିନ୍ ରେକର୍ଡ୍ ସେସନ୍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରିବେ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ଆପଣ ରେକର୍ଡ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ଆପଣ ଏକ ଆପ ରେକର୍ଡ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ଡିଭାଇସ ଅଡିଓ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ମ୍ୟୁଜିକ, କଲ ଏବଂ ରିଂଟୋନଗୁଡ଼ିକ ପରି ଆପଣଙ୍କ ଡିଭାଇସରୁ ସାଉଣ୍ଡ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ପଠାନ୍ତୁ"</string> <string name="cancel" msgid="1089011503403416730">"ବାତିଲ କରନ୍ତୁ"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ଆପ ଲୋଗୋ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ପ୍ରାମାଣିକତା ବାତିଲ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ନୂଆ ଡିଭାଇସ ପେୟାର କରିବାକୁ କ୍ଲିକ କରନ୍ତୁ"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ପ୍ରିସେଟକୁ ଅପଡେଟ କରାଯାଇପାରିଲା ନାହିଁ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ପ୍ରିସେଟ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"ଲାଇଭ କେପ୍ସନ"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ଲାଇଭ କେପ୍ସନ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ କରିବେ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ଡିଭାଇସର କେମେରାକୁ ଅନବ୍ଲକ କରିବେ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ଡିଭାଇସର କ୍ୟାମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ଅନବ୍ଲକ୍ କରିବେ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ସେଟିଂସ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ବନ୍ଦ ଅଛି"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ସେଟ ଅପ କରନ୍ତୁ"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ସେଟିଂସରେ ପରିଚାଳନା କରନ୍ତୁ"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{କୌଣସି ସକ୍ରିୟ ମୋଡ ନାହିଁ}=1{{mode} ସକ୍ରିୟ ଅଛି}other{# ମୋଡ ସକ୍ରିୟ ଅଛି}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ଆଲାର୍ମ, ରିମାଇଣ୍ଡର୍, ଇଭେଣ୍ଟ ଏବଂ ଆପଣ ନିର୍ଦ୍ଦିଷ୍ଟ କରିଥିବା କଲର୍ଙ୍କ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ଆଲାର୍ମ ବ୍ୟତୀତ ଆପଣଙ୍କ ଧ୍ୟାନ ଅନ୍ୟ କୌଣସି ଧ୍ୱନୀ ଏବଂ ଭାଇବ୍ରେଶନ୍ରେ ଆକର୍ଷଣ କରାଯିବନାହିଁ। ମ୍ୟୁଜିକ୍, ଭିଡିଓ ଏବଂ ଗେମ୍ ସମେତ ନିଜେ ଚଲାଇବାକୁ ବାଛିଥିବା ଅନ୍ୟ ସବୁକିଛି ଆପଣ ଶୁଣିପାରିବେ।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"କଷ୍ଟମାଇଜ୍ କରନ୍ତୁ"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ଲକ ସ୍କ୍ରିନରେ ଥିବା ୱିଜେଟଗୁଡ଼ିକ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"ଲକ ସ୍କ୍ରିନରେ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ୱିଜେଟ ଯୋଗ କରାଯାଇଛି"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ଖାରଜ କରନ୍ତୁ"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ ଆପଣଙ୍କ ଡିଭାଇସରୁ ପ୍ଲେ ହେଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ସମସ୍ତ ସୂଚନାକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ରହିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ ଏବଂ ଆପଣ ପ୍ଲେ କରୁଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ରେକର୍ଡିଂ ବା କାଷ୍ଟିଂ ଆରମ୍ଭ କରିବେ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ ଆପଣଙ୍କ ଡିଭାଇସରୁ ପ୍ଲେ ହେଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ସମସ୍ତ ସୂଚନାକୁ ଏହି ଫଙ୍କସନ ପ୍ରଦାନ କରୁଥିବା ସେବାର ଆକ୍ସେସ ରହିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ ଏବଂ ଆପଣ ପ୍ଲେ କରୁଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ଏକ ସିଙ୍ଗଲ ଆପ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ଏକ ଆପକୁ ସେୟାର କିମ୍ବା ରେକର୍ଡ କରନ୍ତୁ"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ସହ ରେକର୍ଡିଂ ବା କାଷ୍ଟିଂ ଆରମ୍ଭ କରିବେ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ଆପଣ ଏକ ଆପ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ଆରମ୍ଭ କରନ୍ତୁ"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ସହ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ସେୟାର କରନ୍ତୁ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ଗୋଟିଏ ଆପ ସେୟାର କରନ୍ତୁ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ଆପଣ ଆପଣଙ୍କ ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସେୟାର କରିବା ସମୟରେ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ଆପଣ ଏକ ଆପ ସେୟାର କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଏହି ବିକଳ୍ପକୁ ଅକ୍ଷମ କରିଛି"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"କାଷ୍ଟିଂ ଆରମ୍ଭ କରିବେ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ଆପଣ କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ଆପଣ ଏକ ଆପ କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପାଇଁ ସତର୍କ ରୁହନ୍ତୁ।"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"କାଷ୍ଟିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ କାଷ୍ଟ କରିବେ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ଗୋଟିଏ ଆପକୁ କାଷ୍ଟ କରନ୍ତୁ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ କାଷ୍ଟ କରନ୍ତୁ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"ଆପଣ ଆପଣଙ୍କ ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ କାଷ୍ଟ କରିବା ସମୟରେ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ସବୁକିଛି ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ଆପଣ ଏକ ଆପ କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛି ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"କାଷ୍ଟ ସ୍କ୍ରିନ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ସେୟାରିଂ ଆରମ୍ଭ କରିବେ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ଆପଣ ଏକ ଆପ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ଆରମ୍ଭ କରନ୍ତୁ"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ପରବର୍ତ୍ତୀ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ଆପଣ ଆପ୍ସ ସୁଇଚ କଲେ ସେୟାରିଂ ବିରତ ହୁଏ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ଏହା ପରିବର୍ତ୍ତେ ଏହି ଆପ ସେୟାର କରନ୍ତୁ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ପୁଣି ସୁଇଚ କରନ୍ତୁ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ଆକ୍ସେସିବିଲିଟୀ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"କୀବୋର୍ଡ ସର୍ଟକଟ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ସର୍ଚ୍ଚ ସର୍ଟକଟ"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"କୌଣସି ସର୍ଚ୍ଚ ଫଳାଫଳ ନାହିଁ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ଆଇକନକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ଆଇକନକୁ ବିସ୍ତାର କରନ୍ତୁ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"କିମ୍ବା"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ହୋମ ଜେଶ୍ଚର"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ଆକ୍ସନ କୀ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ହୋଇଗଲା"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ବଢ଼ିଆ କାମ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ପଛକୁ ଫେରନ୍ତୁ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ପଛକୁ ଫେରିବା ପାଇଁ ଯେ କୌଣସି ସ୍ଥାନରେ ତିନି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ବାମ କିମ୍ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ।\n\nଏଥିପାଇଁ ଆପଣ କୀବୋର୍ଡ ସର୍ଟକଟ ଆକ୍ସନ + ESC ମଧ୍ୟ ବ୍ୟବହାର କରିପାରିବେ।"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ହୋମକୁ ଯାଆନ୍ତୁ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ସ୍କିନର ତଳୁ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ।"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ଡାହାଣ ଏବଂ ବାମକୁ ତିନି ଆଙ୍ଗୁଠି ମୁଭ କରୁଥିବା ଟଚପେଡ ଦେଖାଉଛି"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ଡିଭାଇସ ସ୍କ୍ରିନ ବେକ ଜେଶ୍ଚର ପାଇଁ ଆନିମେସନ ଦେଖାଉଛି"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dରୁ %1$d ନମ୍ବର ଲେଭେଲ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ହୋମ କଣ୍ଟ୍ରୋଲ୍ସ"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ହୋମକୁ ଯିବା ପାଇଁ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରିବାକୁ, ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ଆପଣଙ୍କ ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ଲୁଚା ଯାଇଥିବା"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ଭ୍ୟୁ କରିବାକୁ ଅନଲକ କରନ୍ତୁ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ପଛକୁ ଫେରିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ବାମ ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ହୋମକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ଟଚପେଡ ବ୍ୟବହାର କରନ୍ତୁ"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ଯେ କୌଣସି ସମୟରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ। ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ଅତିରିକ୍ତ ଡିମ ବର୍ତ୍ତମାନ ଉଜ୍ଜ୍ୱଳତା ବାରର ଅଂଶ ଅଟେ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ବର୍ତ୍ତମାନ ଆପଣ ଆପଣଙ୍କ ସ୍କ୍ରିନର ଶୀର୍ଷରୁ ଉଜ୍ଜ୍ୱଳତାର ଲେଭେଲ ହ୍ରାସ କରି ସ୍କ୍ରିନକୁ ଅତିରିକ୍ତ ଡିମ କରିପାରିବେ।\n\nଆପଣ ଏକ ଡାର୍କ ପରିବେଶରେ ଥିଲେ ଏହା ସବୁଠାରୁ ଭଲ କାମ କରେ।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ଅତିରିକ୍ତ ଡିମ ସର୍ଟକଟକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ଅତିରିକ୍ତ ଡିମର ସର୍ଟକଟ କାଢ଼ି ଦିଆଯାଇଛି। ଆପଣଙ୍କ ଉଜ୍ଜ୍ୱଳତା ହ୍ରାସ କରିବା ପାଇଁ ନିୟମିତ ଉଜ୍ଜ୍ୱଳତା ବାର ବ୍ୟବହାର କରନ୍ତୁ।"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index ef642ffb0dd6..281f0e062613 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ਕੀ ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰਨੀ ਹੈ?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਰਿਕਾਰਡਿੰਗ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ਆਡੀਓ ਰਿਕਾਰਡ ਕਰੋ"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"ਡੀਵਾਈਸ ਆਡੀਓ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਧੁਨੀ, ਜਿਵੇਂ ਕਿ ਸੰਗੀਤ, ਕਾਲਾਂ ਅਤੇ ਰਿੰਗਟੋਨਾਂ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ਭੇਜੋ"</string> <string name="cancel" msgid="1089011503403416730">"ਰੱਦ ਕਰੋ"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ਐਪ ਲੋਗੋ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ਤਸਦੀਕ ਕਰੋ"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ਪ੍ਰਮਾਣੀਕਰਨ ਰੱਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"\'ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ\' \'ਤੇ ਕਲਿੱਕ ਕਰੋ"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ਪ੍ਰੀਸੈੱਟ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ਪ੍ਰੀਸੈੱਟ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"ਲਾਈਵ ਸੁਰਖੀਆਂ"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ਲਾਈਵ ਸੁਰਖੀਆਂ"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ਕੀ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰੇ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਨੂੰ ਅਣਬਲਾਕ ਕਰਨਾ ਹੈ?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ਬੰਦ"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ਸੈੱਟਅੱਪ ਕਰੋ"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ਕੋਈ ਕਿਰਿਆਸ਼ੀਲ ਮੋਡ ਨਹੀਂ ਹੈ}=1{{mode} ਕਿਰਿਆਸ਼ੀਲ ਹੈ}other{# ਮੋਡ ਕਿਰਿਆਸ਼ੀਲ ਹਨ}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ, ਯਾਦ-ਦਹਾਨੀਆਂ, ਵਰਤਾਰਿਆਂ, ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਨਿਰਧਾਰਤ ਕੀਤੇ ਕਾਲਰਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ, ਲਾਕ ਸਕ੍ਰੀਨ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ਖਾਰਜ ਕਰੋ"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਤੁਹਾਡੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ਕੀ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ਇਸ ਫੰਕਸ਼ਨ ਦੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਤੁਹਾਡੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ਇਕਹਿਰੀ ਐਪ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰੋ ਜਾਂ ਰਿਕਾਰਡ ਕਰੋ"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"ਕੀ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨਾਲ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ਸ਼ੁਰੂ ਕਰੋ"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ਕੀ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨਾਲ ਆਪਣੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ਇੱਕ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖ ਰਹੀ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> \'ਤੇ ਵੀ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ਕਿਸੇ ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਉਸ ਐਪ \'ਤੇ ਦਿਖ ਰਹੀ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨੂੰ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੇ ਇਸ ਵਿਕਲਪ ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਹੈ"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ਕੀ ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਿਸੇ ਐਪ ਨੂੰ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰੋ"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ਕੀ ਸਕ੍ਰੀਨ ਨੂੰ ਕਾਸਟ ਕਰਨਾ ਹੈ?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ਇੱਕ ਐਪ ਨੂੰ ਕਾਸਟ ਕਰੋ"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਕਾਸਟ ਕਰੋ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਕਾਸਟ ਕਰਨ ਦੌਰਾਨ, ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖ ਰਹੀ ਹਰੇਕ ਚੀਜ਼ ਦੂਸਰੀ ਸਕ੍ਰੀਨ \'ਤੇ ਵੀ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ਕਿਸੇ ਐਪ ਨੂੰ ਕਾਸਟ ਕਰਨ ਦੌਰਾਨ, ਉਸ ਐਪ \'ਤੇ ਦਿਖ ਰਹੀ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਸਾਰੇ ਲੋਕਾਂ ਨੂੰ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"ਸਕ੍ਰੀਨ ਕਾਸਟ ਕਰੋ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"ਕੀ ਸਾਂਝਾਕਰਨ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ਸ਼ੁਰੂ ਕਰੋ"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ਅੱਗੇ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ਐਪਾਂ ਸਵਿੱਚ ਕਰਨ \'ਤੇ ਸਾਂਝਾਕਰਨ ਰੁਕ ਜਾਂਦਾ ਹੈ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ਇਸਦੀ ਬਜਾਏ ਇਹ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ਵਾਪਸ ਸਵਿੱਚ ਕਰੋ"</string> @@ -612,7 +624,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਤੁਹਾਡੀਆਂ ਐਪਾਂ ਦੀ ਵਰਤੋਂ, ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਅਤੇ ਤੁਹਾਡੇ ਸਕ੍ਰੀਨ ਸਮੇਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਦੇਖ ਅਤੇ ਉਸਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੇ ਹਨ।"</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"ਟਰੱਸਟ-ਏਜੰਟ ਵੱਲੋਂ ਅਣਲਾਕ ਰੱਖਿਆ ਗਿਆ"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ਡੀਵਾਈਸ ਲਾਕ ਕੀਤਾ ਗਿਆ ਸੀ, ਬਹੁਤ ਸਾਰੀਆਂ ਪ੍ਰਮਾਣੀਕਰਨ ਕੋਸ਼ਿਸ਼ਾਂ ਕੀਤੀਆਂ ਗਈਆਂ"</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"ਬਹੁਤ ਵਾਰੀ ਪ੍ਰਮਾਣੀਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਕਰਨ ਕਰਕੇ ਡੀਵਾਈਸ ਲਾਕ ਹੋ ਗਿਆ ਸੀ"</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ\nਪ੍ਰਮਾਣੀਕਰਨ ਅਸਫਲ ਰਿਹਾ"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"ਧੁਨੀ ਸੈਟਿੰਗਾਂ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ਪਹੁੰਚਯੋਗਤਾ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ਖੋਜ ਸੰਬੰਧੀ ਸ਼ਾਰਟਕੱਟ"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ਕੋਈ ਖੋਜ ਨਤੀਜਾ ਨਹੀਂ ਮਿਲਿਆ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ਪ੍ਰਤੀਕ ਨੂੰ ਸਮੇਟੋ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ਪ੍ਰਤੀਕ ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ਜਾਂ"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ਹੋਮ \'ਤੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ਕਾਰਵਾਈ ਕੁੰਜੀ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ਹੋ ਗਿਆ"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"ਬਹੁਤ ਵਧੀਆ!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ਵਾਪਸ ਜਾਓ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ਵਾਪਸ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਕਿਤੇ ਵੀ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।\n\nਤੁਸੀਂ ਇਸ ਲਈ ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ Action + ESC ਦੀ ਵਰਤੋਂ ਵੀ ਕਰ ਸਕਦੇ ਹੋ।"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ਹੋਮ \'ਤੇ ਜਾਓ"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਜਾਣ ਲਈ, ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨੂੰ ਸੱਜੇ ਅਤੇ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਲਿਜਾਂਦੇ ਹੋਏ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"ਡੀਵਾਈਸ ਦੀ ਸਕ੍ਰੀਨ \'ਤੇ ਪਿੱਛੇ ਜਾਣ ਵਾਲੇ ਇਸ਼ਾਰੇ ਲਈ ਐਨੀਮੇਸ਼ਨ ਦਿਖਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ਕੀ-ਬੋਰਡ ਬੈਕਲਾਈਟ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ਵਿੱਚੋਂ %1$d ਪੱਧਰ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ਹੋਮ ਕੰਟਰੋਲ"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ਹਾਲੀਆ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ਅਸਪਸ਼ਟ ਬਣਾਇਆ ਗਿਆ"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ਪਿੱਛੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਆਪਣੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਵਰਤੋ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਕਾਰਵਾਈ ਕੁੰਜੀ ਦਬਾਓ। ਹੋਰ ਇਸ਼ਾਰਿਆਂ ਨੂੰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਹੁਣ ਚਮਕ ਪੱਟੀ ਦਾ ਹਿੱਸਾ ਹੈ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ਤੁਸੀਂ ਹੁਣ ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਸਿਖਰ ਤੋਂ ਚਕਮ ਦੇ ਪੱਧਰ ਨੂੰ ਹੋਰ ਵੀ ਘੱਟ ਕਰ ਕੇ ਸਕ੍ਰੀਨ ਦੀ ਚਮਕ ਨੂੰ ਜ਼ਿਆਦਾ ਘੱਟ ਕਰ ਸਕਦੇ ਹੋ।\n\nਇਹ ਉਦੋਂ ਬਿਹਤਰੀਨ ਕੰਮ ਕਰਦੀ ਹੈ, ਜਦੋਂ ਤੁਸੀਂ ਹਨੇਰੇ ਵਿੱਚ ਹੁੰਦੇ ਹੋ।"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਸ਼ਾਰਟਕੱਟ ਹਟਾਓ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਸ਼ਾਰਟਕੱਟ ਹਟਾਇਆ ਗਿਆ। ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੀ ਚਕਮ ਨੂੰ ਘੱਟ ਕਰਨ ਲਈ, ਨਿਯਮਿਤ ਚਮਕ ਪੱਟੀ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index d0e1e11e5727..47330bc48103 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Nagrywanie ekranu"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Rozpocząć nagrywanie?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Podczas nagrywania Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Podczas nagrywania treści z aplikacji Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Zacznij nagrywać"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nagrywaj dźwięk"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Dźwięki z urządzenia"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Dźwięki odtwarzane na urządzeniu, na przykład muzyka, połączenia i dzwonki"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Wyślij"</string> <string name="cancel" msgid="1089011503403416730">"Anuluj"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo aplikacji"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potwierdź"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Spróbuj jeszcze raz"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Kliknij, by anulować uwierzytelnianie"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknij, aby sparować nowe urządzenie"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nie udało się zaktualizować gotowego ustawienia"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Gotowe ustawienie"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Napisy na żywo"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Napisy na żywo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokować mikrofon urządzenia?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokować aparat urządzenia?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokować aparat i mikrofon urządzenia?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ustawienia"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string> <string name="zen_mode_off" msgid="1736604456618147306">"Wył."</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Skonfiguruj"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Zarządzaj w ustawieniach"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Brak aktywnych trybów}=1{Tryb {mode} jest aktywny}few{# tryby są aktywne}many{# trybów jest aktywnych}other{# trybu jest aktywne}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów, przypomnień, wydarzeń i połączeń od wybranych osób. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nie będą Cię niepokoić żadne dźwięki ani wibracje z wyjątkiem alarmów. Będziesz słyszeć wszystkie odtwarzane treści, takie jak muzyka, filmy czy gry."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Dostosuj"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widżety na ekranie blokady"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> został dodany do ekranu blokady"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Dostosuj"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zamknij"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Podczas nagrywania i przesyłania aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> będzie mieć dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Rozpocząć nagrywanie lub przesyłanie?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Podczas nagrywania i przesyłania usługa udostępniająca tę funkcję będzie miała dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Cały ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Pojedyncza aplikacja"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Udostępnianie i nagrywanie aplikacji"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Rozpocząć nagrywanie lub przesyłanie za pomocą aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Rozpocznij"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Udostępnić ekran aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Udostępnij jedną aplikację"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Udostępnij cały ekran"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kiedy udostępniasz treści z całego ekranu, aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do całości obrazu z wyświetlacza. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kiedy udostępniasz obraz z aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, widoczne jest wszystko to, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Udostępnij ekran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ma wyłączoną tę opcję"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Rozpocząć przesyłanie?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Podczas przesyłania, Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Podczas przesyłania treści z aplikacji Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Rozpocznij przesyłanie"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Włączyć przesyłanie treści wyświetlanych na ekranie?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Przesyłanie obrazu z jednej aplikacji"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Przesyłanie obrazu z całego ekranu"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kiedy przesyłasz treści z całego ekranu, widoczny jest cały obraz z wyświetlacza. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kiedy przesyłasz obraz z aplikacji, widoczne jest wszystko to, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Prześlij ekran"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Rozpocząć udostępnianie?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Podczas udostępniania, nagrywania lub przesyłania treści Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Podczas udostępniania, nagrywania lub przesyłania treści Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, dźwięku i filmów."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Rozpocznij"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Dalej"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Udostępnianie zostanie wstrzymane, gdy przełączysz aplikacje"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Udostępnij tę aplikację"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Wróć"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Ułatwienia dostępu"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Skróty klawiszowe"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Skróty do wyszukiwania"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Brak wyników wyszukiwania"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zwijania"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozwijania"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"lub"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest przejścia na ekran główny"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Klawisz działania"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotowe"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Świetnie!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Wróć"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"3 palce na touchpadzie poruszające się w prawo i w lewo"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekran urządzenia z animacją gestu cofania"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Aby przejść wstecz, przesuń 3 palcami w lewo lub w prawo w dowolnym miejscu touchpada.\n\nMożesz też użyć do tego skrótu klawiszowego Action + ESC."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Brawo!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Gest przejścia wstecz został opanowany."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Otwórz stronę główną"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Aby w dowolnym momencie wyświetlić ekran główny, przesuń od dołu ekranu w górę 3 palcami."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Super!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Gest przechodzenia na ekran główny został opanowany."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Klawisz działania"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Aby uzyskać dostęp do aplikacji, naciśnij klawisz działania na klawiaturze."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gratulacje!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Gest klawisza działania został opanowany.\n\nKlawisz działania + / pokazuje wszystkie dostępne skróty."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podświetlenie klawiatury"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Poziom %1$d z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Sterowanie domem"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Aby przejść do ekranu głównego, przesuń w górę za pomocą 3 palców na touchpadzie"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Aby wyświetlić ostatnie aplikacje, przesuń w górę za pomocą 3 palców na touchpadzie i przytrzymaj."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aby wyświetlić wszystkie swoje aplikacje, naciśnij klawisz działania na klawiaturze"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Usunięto"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Odblokuj, aby zobaczyć"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Przechodzenie wstecz za pomocą touchpada"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Przesuń w prawo lub lewo za pomocą 3 palców. Kliknij, aby poznać więcej gestów."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Przechodzenie do ekranu głównego za pomocą touchpada"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Przesuń w górę za pomocą 3 palców i przytrzymaj. Kliknij, aby poznać więcej gestów."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Wyświetlanie wszystkich aplikacji za pomocą klawiatury"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Naciśnij klawisz działania w dowolnym momencie. Kliknij, aby poznać więcej gestów."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatkowe przyciemnienie jest teraz częścią paska jasności"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Możesz teraz dodatkowo przyciemnić ekran, jeszcze bardziej zmniejszając poziom jasności u góry ekranu.\n\nTa funkcja sprawdza się najlepiej, gdy jesteś w ciemnym otoczeniu."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Usuń skrót do dodatkowego przyciemnienia"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Skrót do dodatkowego przyciemnienia został usunięty. Aby zmniejszyć jasność, użyj standardowego paska jasności."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index e74f57899b3f..35a3c11fa02f 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Iniciar gravação?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Durante a gravação, o Android tem acesso às informações na tela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Enquanto você grava um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Iniciar gravação"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar áudio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Áudio do dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons do dispositivo, como música, chamadas e toques"</string> @@ -139,9 +149,9 @@ <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Interromper compartilhamento"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Transmitindo a tela"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Parar transmissão?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Você está transmitindo a tela inteira para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Você está transmitindo a tela inteira para o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Você está transmitindo a tela inteira para um dispositivo por perto"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para o <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para o dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para um dispositivo por perto"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Você está transmitindo para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Você está transmitindo para um dispositivo por perto"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotipo do app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predefinição"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Legenda instantânea"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Legenda instantânea"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerenciar nas configurações"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}one{# modo está ativo}many{# de modos estão ativos}other{# modos estão ativos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"O widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> foi adicionado à tela de bloqueio"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"O app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acesso a todas as informações na tela ou reproduzidas no dispositivo, como gravações ou transmissões. Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudios que você tocar."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Iniciar gravação ou transmissão?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tela cheia"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Um único app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Compartilhar ou gravar um app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Iniciar gravação ou transmissão com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando você compartilha, grava ou transmite a tela, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Início"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou essa opção"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmissão?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando você transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando você transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Começar a transmissão"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Transmitir a tela?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmitir um app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmitir tela inteira"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Quando você está transmitindo a tela inteira, tudo nela fica visível. Por isso, tenha cuidado com senhas, detalhes da forma de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Quando você transmite um app, todas as informações visíveis ou abertas nele ficam visíveis. Por isso, tenha cuidado com senhas, detalhes da forma de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Transmitir tela"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Começar a compartilhar?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Quando você compartilha, grava ou transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Quando você compartilha, grava ou transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Início"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Próxima"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"O compartilhamento é pausado na troca de apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Compartilhar este app"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Voltar"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Acessibilidade"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Atalhos do teclado"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atalhos de pesquisa"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nenhum resultado de pesquisa"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad.\n\nVocê também pode usar o atalho de teclado Ação + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para acessar sua tela inicial a qualquer momento, deslize de baixo para cima na tela com três dedos."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Encoberto"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquear para visualizar"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"O recurso Escurecer a tela agora faz parte da barra de brilho"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, na parte de cima, é possível usar o recurso Escurecer a tela, que diminui ainda mais o nível de brilho.\n\nIsso funciona melhor quando você está em um ambiente escuro."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho de Escurecer a tela"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho de Escurecer a tela removido. Use a barra normal para diminuir o brilho."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index a21f47523820..2788bbbfc9ab 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de ecrã"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Iniciar a gravação?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Enquanto está a gravar, o Android tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Enquanto está a gravar uma app, o Android tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Começar gravação"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar áudio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Áudio do dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"O som do dispositivo, como música, chamadas e toques."</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logótipo da app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação."</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para sincronizar um novo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predefinição"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Legendas instantâneas"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Legendas instantâneas"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmara do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Quer desbloquear a câmara e o microfone?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Definições"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerir nas definições"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}many{# modos estão ativos}other{# modos estão ativos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Não é incomodado por sons e vibrações, exceto de alarmes, lembretes, eventos e autores de chamadas que especificar. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Não é incomodado por sons e vibrações, exceto de alarmes. Continua a ouvir tudo o que optar por reproduzir, incluindo música, vídeos e jogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar lentamente • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets no ecrã de bloqueio"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> adicionado ao ecrã de bloqueio"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize rapidamente para a esquerda para iniciar o tutorial coletivo"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"A app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vai ter acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou a transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Começar a gravar ou a transmitir?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que fornece esta função vai ter acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou a transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Ecrã inteiro"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Só uma app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Partilhe ou grave uma app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Começar a gravar ou a transmitir com a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando está a partilhar, gravar ou transmitir, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando está a partilhar, gravar ou transmitir uma app, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partilhar o seu ecrã com a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partilhar uma app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partilhar ecrã inteiro"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando está a partilhar o ecrã inteiro, tudo o que estiver no ecrã é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando está a partilhar uma app, tudo o que é mostrado ou reproduzido nessa app é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partilhar ecrã"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou esta opção"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmitir?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando está a transmitir conteúdo, o Android tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando está a transmitir uma app, o Android tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Começar a transmitir"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Transmitir o ecrã?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmitir uma app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmitir ecrã inteiro"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Quando está a transmitir todo o ecrã, tudo o que estiver no seu ecrã é visível. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Quando está a transmitir uma app, tudo o que é mostrado ou reproduzido nessa app fica visível. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Transmitir ecrã"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Começar a partilhar?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Quando está a partilhar, gravar ou transmitir conteúdo, o Android tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Quando está a partilhar, gravar ou transmitir uma app, o Android tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Iniciar"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Seguinte"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"A partilha é pausada quando muda de app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Partilhar antes esta app"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Voltar"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Acessibilidade"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Atalhos de teclado"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atalhos de pesquisa"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nenhum resultado da pesquisa"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone de reduzir"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone de expandir"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para aceder ao ecrã principal"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluir"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad a mostrar três dedos a moverem-se para a direita e esquerda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecrã de dispositivo a mostrar uma animação do gesto para retroceder"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para retroceder, deslize rapidamente para a esquerda ou direita com 3 dedos em qualquer parte do touchpad.\n\nPara o fazer, também pode usar o atalho de teclado Ação + ESC."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Muito bem!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Concluiu o gesto para retroceder."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Aceder ao ecrã principal"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para aceder ao ecrã principal em qualquer altura, deslize rapidamente com 3 dedos de baixo para cima no ecrã."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Boa!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Concluiu o gesto para aceder ao ecrã principal."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de ação"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para aceder às suas apps, prima a tecla de ação no teclado."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Parabéns!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Concluiu o gesto da tecla de ação.\n\nA ação + / mostra todos os atalhos que tem disponíveis."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlos domésticos"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para aceder ao ecrã principal, deslize rapidamente para cima com 3 dedos no touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para ver as apps recentes, deslize rapidamente para cima e mantenha premido com 3 dedos no touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas as suas apps, prima a tecla de ação no teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Revisto"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloqueie para ver"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para retroceder"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize rapidamente para a esquerda ou direita com 3 dedos. Toque para aprender mais gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para aceder ao ecrã principal"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize rapidamente para cima e mantenha premido com 3 dedos. Toque para aprender mais gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todas as apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prima a tecla de ação em qualquer altura. Toque para aprender mais gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Agora, o escurecimento extra faz parte da barra do brilho"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, pode tornar o ecrã ainda mais escuro reduzindo ainda mais o nível de brilho a partir da parte superior do ecrã.\n\nIsto funciona melhor quando está num ambiente escuro."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho do escurecimento extra"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho do escurecimento extra removido. Para reduzir o brilho, use a barra do brilho normal."</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index e74f57899b3f..35a3c11fa02f 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Iniciar gravação?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Durante a gravação, o Android tem acesso às informações na tela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Enquanto você grava um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Iniciar gravação"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Gravar áudio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Áudio do dispositivo"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons do dispositivo, como música, chamadas e toques"</string> @@ -139,9 +149,9 @@ <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Interromper compartilhamento"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Transmitindo a tela"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Parar transmissão?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Você está transmitindo a tela inteira para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Você está transmitindo a tela inteira para o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Você está transmitindo a tela inteira para um dispositivo por perto"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para o <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para o dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Você está transmitindo o app <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> para um dispositivo por perto"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"Você está transmitindo para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"Você está transmitindo para um dispositivo por perto"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Enviar"</string> <string name="cancel" msgid="1089011503403416730">"Cancelar"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotipo do app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmar"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tentar novamente"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Toque para cancelar a autenticação"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Clique para parear o novo dispositivo"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predefinição"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Legenda instantânea"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Legenda instantânea"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Desbloquear o microfone do dispositivo?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Desbloquear a câmera do dispositivo?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Desbloquear a câmera e o microfone do dispositivo?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerenciar nas configurações"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}one{# modo está ativo}many{# de modos estão ativos}other{# modos estão ativos}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Você não será perturbado por sons e vibrações, exceto alarmes, lembretes, eventos e chamadas de pessoas especificadas. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Você não será perturbado por sons e vibrações, exceto alarmes. No entanto, você ouvirá tudo o que decidir reproduzir, como músicas, vídeos e jogos."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carga lenta • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgets na tela de bloqueio"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"O widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> foi adicionado à tela de bloqueio"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"O app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> terá acesso a todas as informações na tela ou reproduzidas no dispositivo, como gravações ou transmissões. Isso inclui informações como senhas, detalhes de pagamento, fotos, mensagens e áudios que você tocar."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Iniciar gravação ou transmissão?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tela cheia"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Um único app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Compartilhar ou gravar um app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Iniciar gravação ou transmissão com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando você compartilha, grava ou transmite a tela, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Início"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou essa opção"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmissão?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando você transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando você transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Começar a transmissão"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Transmitir a tela?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmitir um app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmitir tela inteira"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Quando você está transmitindo a tela inteira, tudo nela fica visível. Por isso, tenha cuidado com senhas, detalhes da forma de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Quando você transmite um app, todas as informações visíveis ou abertas nele ficam visíveis. Por isso, tenha cuidado com senhas, detalhes da forma de pagamento, mensagens, fotos, áudios e vídeos."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Transmitir tela"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Começar a compartilhar?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Quando você compartilha, grava ou transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Quando você compartilha, grava ou transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Início"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Próxima"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"O compartilhamento é pausado na troca de apps"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Compartilhar este app"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Voltar"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Acessibilidade"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Atalhos do teclado"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atalhos de pesquisa"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nenhum resultado de pesquisa"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Muito bem!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad.\n\nVocê também pode usar o atalho de teclado Ação + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para acessar sua tela inicial a qualquer momento, deslize de baixo para cima na tela com três dedos."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad mostrando 3 dedos deslizando para a direita e esquerda"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Tela do dispositivo mostrando a animação do gesto de volta"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Se quiser acessar a tela inicial, deslize para cima com três dedos no touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Se quiser ver os apps recentes, deslize para cima e pressione com três dedos no touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todos os apps, pressione a tecla de ação no teclado"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Encoberto"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquear para visualizar"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para voltar"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize para a esquerda ou direita usando três dedos. Toque para aprender outros gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para acessar a tela inicial"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"O recurso Escurecer a tela agora faz parte da barra de brilho"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, na parte de cima, é possível usar o recurso Escurecer a tela, que diminui ainda mais o nível de brilho.\n\nIsso funciona melhor quando você está em um ambiente escuro."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho de Escurecer a tela"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho de Escurecer a tela removido. Use a barra normal para diminuir o brilho."</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index d0895ada88f7..6f1bc67796a5 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Recorder pentru ecran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Începi înregistrarea?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Când înregistrezi, Android are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Când înregistrezi o aplicație, Android are acces la orice se afișează sau se redă în aplicație. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Începe înregistrarea"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Înregistrează audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Conținutul audio de la dispozitiv"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sunetul de la dispozitiv, precum muzică, apeluri și tonuri de apel"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Trimite"</string> <string name="cancel" msgid="1089011503403416730">"Anulează"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Sigla aplicației"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Confirmă"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Încearcă din nou"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Atinge pentru a anula autentificarea"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Dă clic pentru a asocia un nou dispozitiv"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nu s-a putut actualiza presetarea"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Presetare"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Subtitrări live"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitrări live"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Deblochezi microfonul dispozitivului?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Deblochezi camera dispozitivului?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Deblochezi camera și microfonul dispozitivului?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setări"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Dezactivat"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurează"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestionează în setări"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Niciun mod activ}=1{{mode} este activ}few{# moduri sunt active}other{# de moduri sunt active}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Se vor anunța prin sunete și vibrații numai alarmele, mementourile, evenimentele și apelanții specificați de tine. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Se vor anunța prin sunete și vibrații numai alarmele. Totuși, vei auzi tot ce alegi să redai, inclusiv muzică, videoclipuri și jocuri."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizează"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă lent • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgeturi pe ecranul de blocare"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget adăugat pe ecranul de blocare"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizează"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Respinge"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrezi sau proiectezi. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redai."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Începi să înregistrezi sau să proiectezi?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Serviciul care oferă această funcție va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrezi sau proiectezi. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redai."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tot ecranul"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"O singură aplicație"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Distribuie o aplicație sau înregistreaz-o"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Începi să înregistrezi sau să proiectezi cu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Când permiți accesul, înregistrezi sau proiectezi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice se afișează pe ecran sau se redă în aplicație. Prin urmare, ai grijă cu informații cum ar fi parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Începe"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Permiți accesul <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> la ecran?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Permite accesul la o aplicație"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Permite accesul la tot ecranul"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Când permiți accesul la tot ecranul, tot conținutul de pe ecran este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Când permiți accesul la o aplicație, orice conținut se afișează sau se redă în aplicație este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Permite accesul la ecran"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a dezactivat această opțiune"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Începi să proiectezi?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Când proiectezi, Android are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Când proiectezi o aplicație, Android are acces la orice se afișează sau se redă în aplicație. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Începe să proiectezi conținut"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Proiectezi ecranul?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Proiectează o aplicație"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Proiectează tot ecranul"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Când proiectezi tot ecranul, tot conținutul de pe ecran este vizibil. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Când proiectezi o aplicație, orice conținut se afișează sau se redă în aplicație este vizibil. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Proiectează ecranul"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Începi să permiți accesul?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Când permiți accesul, înregistrezi sau proiectezi, Android are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, Android are acces la orice se afișează pe ecran sau se redă în aplicație. Prin urmare, ai grijă cu informații cum ar fi parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Începe"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Înainte"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Trimiterea se oprește când comuți între aplicații"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Trimite această aplicație"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Revino"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilitate"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Comenzi rapide de la tastatură"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Comenzi directe de căutare"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Niciun rezultat al căutării"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Pictograma de restrângere"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Pictograma de extindere"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"sau"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestul Ecran de pornire"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tastă de acțiuni"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gata"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Excelent!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Înapoi"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete oriunde pe touchpad.\n\nPoți folosi și comanda rapidă de la tastatură Action + ESC pentru aceasta."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Înapoi la pagina de pornire"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pentru a accesa oricând ecranul de pornire, glisează în sus cu trei degete din partea de jos a ecranului"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad cu trei degete care se mișcă spre dreapta și spre stânga"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ecran de dispozitiv cu o animație pentru gestul Înapoi"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Iluminarea din spate a tastaturii"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivelul %1$d din %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Comenzi pentru locuință"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ca să accesezi pagina de pornire, glisează în sus cu trei degete pe touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ca să vezi aplicațiile recente, glisează în sus și ține apăsat cu trei degete pe touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ca să vezi toate aplicațiile, apasă tasta de acțiuni de pe tastatură"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Ascunsă"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Deblochează pentru a afișa"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Folosește-ți touchpadul ca să revii"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Glisează la stânga sau la dreapta cu trei degete. Atinge ca să înveți mai multe gesturi."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Folosește-ți touchpadul ca să accesezi pagina de pornire"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Glisează în sus și ține apăsat cu trei degete. Atinge ca să înveți mai multe gesturi."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Folosește-ți tastatura ca să vezi toate aplicațiile"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Apasă oricând tasta de acțiuni. Atinge ca să înveți mai multe gesturi."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Luminozitatea redusă suplimentar face acum parte din bara de luminozitate"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Poți reduce suplimentar luminozitatea ecranului dacă scazi nivelul de luminozitate din partea de sus a ecranului.\n\nAcest lucru funcționează cel mai bine într-un mediu întunecat."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Elimină comanda rapidă de luminozitate redusă suplimentar"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"S-a eliminat comanda rapidă de luminozitate redusă suplimentar. Ca să reduci luminozitatea, folosește bara obișnuită de luminozitate."</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 3811185f62d3..2220ff7cdd2c 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Запись видео с экрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Начать запись?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Когда вы записываете видео с экрана, Android получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Когда вы записываете экран приложения, система Android получает доступ ко всему, что видно или воспроизводится в нем. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Начать запись"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Записывать аудио"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук с устройства"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук с вашего устройства, например музыка, звонки и рингтоны"</string> @@ -127,19 +137,19 @@ <string name="screenrecord_save_error" msgid="5862648532560118815">"Не удалось сохранить запись видео с экрана."</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Не удалось начать запись видео с экрана."</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Остановить запись?"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Вы записываете свой экран."</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Вы записываете весь экран."</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Вы записываете экран приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Остановить запись"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Демонстрация экрана"</string> - <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Закрыть совместный доступ к экрану?"</string> + <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Прекратить показ экрана?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Вы демонстрируете свой экран в приложении \"<xliff:g id="HOST_APP_NAME">%1$s</xliff:g>\"."</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Вы демонстрируете свой экран в приложении."</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Вы демонстрируете экран приложения \"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>\"."</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Вы демонстрируете экран приложения."</string> - <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Закрыть доступ"</string> + <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Прекратить показ"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Трансляция экрана"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"Прекратить трансляцию?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Вы транслируете свой экран на устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"Вы транслируете весь экран на устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"Вы транслируете свой экран на устройство поблизости."</string> <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"Вы транслируете приложение \"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>\" на устройство \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\"."</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"Вы транслируете приложение \"<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>\" на устройство поблизости."</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Отправить"</string> <string name="cancel" msgid="1089011503403416730">"Отмена"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Логотип приложения"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Подтвердить"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Повторить попытку"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Нажмите, чтобы отменить аутентификацию"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Нажмите, чтобы подключить новое устройство"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не удалось обновить набор настроек."</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набор настроек"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Автосубтитры"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Автосубтитры"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Разблокировать микрофон устройства?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Разблокировать камеру устройства?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Разблокировать камеру и микрофон устройства?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Отключено"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Настроить"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Открыть настройки"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Включено 0 режимов}=1{Включен режим \"{mode}\"}one{Включен # режим}few{Включено # режима}many{Включено # режимов}other{Включено # режима}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника, напоминаний, уведомлений о мероприятиях и звонков от помеченных контактов. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Настроить"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Медленная зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виджеты на заблокированном экране"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" добавлен на заблокированный экран."</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Настроить"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыть"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Во время записи или трансляции у приложения \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" будет доступ ко всему, что видно или воспроизводится на устройстве, в том числе к паролям, сведениям о способах оплаты, фотографиям, сообщениям и аудио."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Начать запись или трансляцию?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Во время записи или трансляции у сервиса, предоставляющего эту функцию, будет доступ ко всему, что видно или воспроизводится на устройстве, включая пароли, сведения о способах оплаты, фотографии, сообщения и аудио."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Весь экран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Отдельное приложение"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Демонстрация или запись экрана приложения"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Начать запись или трансляцию через приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Когда вы демонстрируете, транслируете экран или записываете видео с него, приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Когда вы демонстрируете, записываете или транслируете экран приложения, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> получает доступ ко всему, что видно или воспроизводится в этом приложении. Будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Начать"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показать экран приложению \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показать приложение"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показать весь экран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"При показе экрана целиком все, что на нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"При показе приложения все, что в нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показать экран"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" отключило эту возможность"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Начать трансляцию?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Во время трансляции система Android получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Когда вы транслируете экран приложения, система Android получает доступ ко всему, что видно или воспроизводится в нем. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Начать трансляцию"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Начать трансляцию экрана?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Транслировать одно приложение"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Транслировать весь экран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Во время трансляции будет видно все, что происходит на экране. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Во время трансляции будет видно все, что происходит в выбранном приложении. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Транслировать экран"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Начать показ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Когда вы демонстрируете, транслируете экран или записываете видео с него, система Android получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Когда вы демонстрируете, записываете или транслируете экран приложения, система Android получает доступ ко всему, что видно или воспроизводится в нем. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Начать"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Далее"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Общий доступ прерывается при переключении приложений"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Открыть доступ к этому приложению"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Переключиться обратно"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Специальные возможности"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Быстрые клавиши"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Найти быстрые клавиши"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ничего не найдено"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Свернуть\""</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Развернуть\""</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест \"на главный экран\""</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиша действия"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Отлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Чтобы вернуться назад, проведите по сенсорной панели тремя пальцами влево или вправо.\n\nВы также можете нажать клавишу действия + Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На главный экран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Чтобы перейти на главный экран, проведите снизу вверх тремя пальцами."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Три пальца двигаются вправо и влево по сенсорной панели"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"На экране устройства показана анимация для жеста \"Назад\""</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Уровень %1$d из %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Управление домом"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Чтобы перейти на главный экран, проведите по сенсорной панели тремя пальцами вверх."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Чтобы увидеть недавние приложения, проведите по сенсорной панели тремя пальцами вверх и удерживайте."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Чтобы открыть список всех своих приложений, нажмите клавишу действия."</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Скрыто"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Разблокируйте экран, чтобы посмотреть."</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Используйте сенсорную панель, чтобы возвращаться назад"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Для этого проведите тремя пальцами влево или вправо. Нажмите, чтобы посмотреть другие жесты."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Используйте сенсорную панель, чтобы переходить на главный экран"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Для этого проведите тремя пальцами вверх и удерживайте. Нажмите, чтобы посмотреть другие жесты."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Открывайте список всех приложений с помощью клавиатуры"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Для этого можно использовать клавишу действия. Нажмите, чтобы посмотреть другие жесты."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Дополнительно уменьшать яркость теперь можно через стандартный ползунок"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Чтобы дополнительно понизить яркость экрана, откройте настройки в его верхней части.\n\nРекомендуем использовать эту функцию, когда вокруг темно."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Удалить быструю команду для дополнительного уменьшения яркости"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Быстрая команда для дополнительного уменьшения яркости удалена. Чтобы изменить уровень яркости, воспользуйтесь стандартным ползунком яркости."</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 46b82e37d673..e4d6f2e12607 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"තිර රෙකෝඩරය"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"පටිගත කිරීම ආරම්භ කරන්න ද?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ඔබ පටිගත කරන අතරේ, Android හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ඔබ යෙදුමක් පටිගත කරන අතරතුර, Android හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"පටිගත කිරීම අරඹන්න"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ඕඩියෝ පටිගත කරන්න"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"උපාංග ඕඩියෝ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"සංගීතය, ඇමතුම් සහ නාද රිද්ම වැනි ඔබේ උපාංගය වෙතින් ශබ්ද"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"යවන්න"</string> <string name="cancel" msgid="1089011503403416730">"අවලංගු කරන්න"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"යෙදුම් ලාංඡනය"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"තහවුරු කරන්න"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"නැවත උත්සාහ කරන්න"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"සත්යාපනය අවලංගු කිරීමට තට්ටු කරන්න"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"නව උපාංගය යුගල කිරීමට ක්ලික් කරන්න"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"පෙර සැකසීම යාවත්කාලීන කළ නොහැකි විය"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"පෙරසැකසුම"</string> - <string name="live_caption_title" msgid="8916875614623730005">"සජීවී සිරස්තල"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"සජීවී සිරස්තල"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"උපාංග මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"උපාංග කැමරාව අවහිර කිරීම ඉවත් කරන්නද?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"උපාංග කැමරාව සහ මයික්රෆෝනය අවහිර කිරීම ඉවත් කරන්නද?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"සැකසීම්"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ක්රියාත්මකයි"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ක්රියාවිරහිතයි"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"පිහිටුවන්න"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"සැකසීම් තුළ කළමනාකරණය කරන්න"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{සක්රිය ප්රකාර නොමැත}=1{{mode} සක්රියයි}one{ප්රකාර #ක් සක්රියයි}other{ප්රකාර #ක් සක්රියයි}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"එලාම සිහිකැඳවීම්, සිදුවීම්, සහ ඔබ සඳහන් කළ අමතන්නන් හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"එලාම හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත. සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු ඔබ වාදනය කිරීමට තෝරන ලද සියලු දේ ඔබට තවම ඇසෙනු ඇත."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"අභිරුචිකරණය"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • සෙමින් ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"අගුළු තිරයෙහි විජට්"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට් අගුළු තිරයට එක් කරන ලදි"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"අභිරුචිකරණය කරන්න"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"අස් කරන්න"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට ඔබේ තිරයේ පෙනෙන හෝ පටිගත කිරීමේ දී හෝ විකාශනය කිරීමේ දී ඔබේ උපාංගයේ වාදනය වන සියලු තොරතුරු වෙත ප්රවේශය ඇත. මෙයට මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවුඩ, සහ ඔබ වාදනය කරන ශ්රව්ය වැනි තොරතුරු ඇතුළත් වේ."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"පටිගත කිරීම හෝ විකාශය කිරීම ආරම්භ කරන්න ද?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"මෙම කාර්යය සපයන සේවාවට තිරයේ පෙනෙන හෝ පටිගත කිරීමේ දී හෝ විකාශනය කිරීමේ දී ඔබේ උපාංගයේ වාදනය වන සියලු තොරතුරු වෙත ප්රවේශය ඇත. මෙයට මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවුඩ, සහ ඔබ වාදනය කරන ශ්රව්ය වැනි තොරතුරු ඇතුළත් වේ."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"සම්පූර්ණ තිරය"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"තනි යෙදුමක්"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"යෙදුමක් බෙදා ගන්න හෝ පටිගත කරන්න"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> සමග පටිගත කිරීම හෝ විකාශය කිරීම ආරම්භ කරන්න ද?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ඔබ බෙදා ගන්නා විට, පටිගත කරන විට, හෝ විකාශනය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"අරඹන්න"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> සමග ඔබේ තිරය බෙදා ගන්න ද?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"එක් යෙදුමක් බෙදා ගන්න"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"සම්පූර්ණ තිරය බෙදා ගන්න"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ඔබ ඔබේ සම්පූර්ණ තිරය බෙදා ගන්නා විට, ඔබේ තිරයේ ඇති ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ඔබ යෙදුමක් බෙදා ගන්නා විට, එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"තිරය බෙදා ගන්න"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> මෙම විකල්පය අබල කර ඇත"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"විකාශය ආරම්භ කරන්න ද?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ඔබ විකාශය කරන විට, Android හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ඔබ යෙදුමක් විකාශය කරන විට, Android හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"විකාශය ආරම්භ කරන්න"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"ඔබේ තිරය විකාශය කරන්න ද?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"එක් යෙදුමක් විකාශය කරන්න"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"සමස්ත තිරය විකාශය කරන්න"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"ඔබ ඔබේ සම්පූර්ණ තිරය විකාශය කරන විට, ඔබේ තිරයේ ඇති ඕනෑම දෙයක් දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ඔබ යෙදුමක් විකාශය කරන විට, එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයක් දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"විකාශ තිරය"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"බෙදා ගැනීම ආරම්භ කරන්න ද?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"ඔබ බෙදා ගන්නා විට, පටිගත කරන විට, හෝ විකාශය කරන විට, Android හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, Android හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"අරඹන්න"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"මීළඟ"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"ඔබ යෙදුම් මාරු කරන විට බෙදා ගැනීම විරාම වේ"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"ඒ වෙනුවට මෙම යෙදුම බෙදා ගන්න"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"ආපසු මාරු වන්න"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ප්රවේශ්යතාව"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"යතුරු පුවරු කෙටි මං"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"කෙටි මං සොයන්න"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"සෙවීම් ප්රතිඵල නැත"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"හැකුළුම් නිරූපකය"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"දිගහැරීම් නිරූපකය"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"හෝ"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"නිවෙස් අභිනය"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ක්රියා යතුර"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"නිමයි"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"අනර්ඝ වැඩක්!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ආපස්සට යන්න"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ආපසු යාමට, ස්පර්ශ පුවරුවවේ ඕනෑම තැනක ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න.\n\nඔබට මේ සඳහා යතුරු පුවරු කෙටිමං ක්රියාව + ESC ද භාවිත කළ හැක."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"මුල් පිටුවට යන්න"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ඕනෑම වේලාවක ඔබේ මුල් තිරයට යාමට, ඔබේ තිරයේ පහළ සිට ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ඇඟිලි තුනක් දකුණට සහ වමට චලනය වන බව පෙන්වන ස්පර්ශක පුවරුව"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"පසුපස අභිනය සඳහා සජීවිකරණය පෙන්වන උපාංග තිරය"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"යතුරු පුවරු පසු ආලෝකය"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dන් %1$d වැනි මට්ටම"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"නිවෙස් පාලන"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"මුල් පිටුවට යාමට, ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"මෑත යෙදුම් බැලීමට, ඉහළට ස්වයිප් කර ස්පර්ශ පුවරුව මත ඇඟිලි තුනකින් අල්ලාගෙන සිටින්න"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ඔබේ සියලුම යෙදුම් බැලීමට, ඔබේ යතුරුපුවරුවේ ක්රියාකාරී යතුර ඔබන්න"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"නැවත සකස් කරන ලද"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"බැලීමට අගුළු හරින්න"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ආපසු යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"මුල් පිටුවට යාමට ඔබේ ස්පර්ශ පුවරුව භාවිත කරන්න"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ඇඟිලි තුනක් භාවිතයෙන් ඉහළට ස්වයිප් කර අල්ලාගෙන සිටින්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"සියලුම යෙදුම් බැලීමට ඔබේ යතුරු පුවරුව භාවිත කරන්න"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ඕනෑම අවස්ථාවක ක්රියාකාරී යතුර ඔබන්න. තව ඉංගිත දැන ගැනීමට තට්ටු කරන්න."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"තවත් අඳුර දැන් දීප්ත තීරුවේ කොටසකි"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ඔබේ තිරයේ ඉහළ සිට දීප්තියේ මට්ටම තවත් අඩු කිරීමෙන් ඔබට දැන් තිරය තවත් අඳුරු කළ හැක.\n\nඔබ අඳුරු පරිසරයක සිටින විට මෙය වඩාත් හොඳින් ක්රියා කරයි."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"තවත් අඳුරු කෙටිමඟ ඉවත් කරන්න"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"තවත් අඳුරු කෙටිමඟ ඉවත් කරන ලදි. ඔබේ දීප්තිය අඩු කිරීමට, සාමාන්ය දීප්ත තීරුව භාවිත කරන්න."</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index b6077396378a..803c27b79d6d 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Rekordér obrazovky"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Chcete spustiť nahrávanie?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Počas nahrávania bude mať Android prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Počas nahrávania v aplikácii bude mať Android prístup k všetkému, čo sa v danej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Spustiť nahrávanie"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrávať zvuk"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk zariadenia"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk zo zariadenia, napríklad hudba, hovory a tóny zvonenia"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Odoslať"</string> <string name="cancel" msgid="1089011503403416730">"Zrušiť"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo aplikácie"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potvrdiť"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Skúsiť znova"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Klepnutím zrušíte overenie"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknutím spárujete nové zariadenie"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Predvoľbu sa nepodarilo aktualizovať"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predvoľba"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Živý prepis"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Živý prepis"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Chcete odblokovať mikrofón zariadenia?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Chcete odblokovať kameru zariadenia?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Chcete odblokovať fotoaparát a mikrofón zariadenia?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavenia"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuté"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastavenie"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Správa v nastaveniach"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žiadne aktívne režimy}=1{{mode} je aktívny}few{# režimy sú aktívne}many{# modes are active}other{# režimov je aktívnych}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky, pripomenutia, udalosti a volajúci, ktorých určíte. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prispôsobiť"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa pomaly • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikácie na uzamknutej obrazovke"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g> bola pridaná na uzamknutú obrazovku"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prispôsobiť"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavrieť"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, ako sú heslá, platobné údaje, fotky, správy a prehrávaný zvuk."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Chcete spustiť nahrávanie alebo prenos?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba poskytujúca túto funkciu bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, ako sú heslá, platobné údaje, fotky, správy a prehrávaný zvuk."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Celá obrazovka"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Jedna aplikácia"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Vyberte aplikáciu, ktorú chcete zdieľať alebo nahrávať"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Chcete spustiť nahrávanie alebo prenos s aktivovaným povolením <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Počas zdieľania, nahrávania alebo prenosu bude mať <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Počas zdieľania, nahrávania alebo prenosu v aplikácii bude mať <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému, čo sa v danej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začať"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chcete zdieľať obrazovku s aplikáciou <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Zdieľať jednu aplikáciu"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Zdieľať celú obrazovku"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri zdieľaní celej obrazovky vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa na nej zobrazuje. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri zdieľaní aplikácie vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa v zdieľanej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Zdieľať obrazovku"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> túto možnosť zakázala"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Chcete spustiť prenos?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Počas prenosu bude mať Android prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Počas prenosu v aplikácii bude mať Android prístup k všetkému, čo sa v danej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Spustiť prenos"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Chcete prenášať obrazovku?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Prenášať jednu aplikáciu"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Prenášať celú obrazovku"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Pri prenášaní celej obrazovky je viditeľný všetok obsah na obrazovke. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Pri prenášaní aplikácie je viditeľný všetok obsah zobrazený alebo prehrávaný v tejto aplikácii. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Prenášať obrazovku"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Chcete spustiť zdieľanie?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Počas zdieľania, nahrávania alebo prenosu bude mať Android prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Počas zdieľania, nahrávania alebo prenosu v aplikácii bude mať Android prístup k všetkému zobrazovanému alebo prehrávaného obsahu v danej aplikácii. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Začať"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Ďalej"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Zdieľanie sa pozastaví, keď prepnete aplikácie"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Zdieľať radšej túto aplikáciu"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Prepnúť späť"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Dostupnosť"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klávesové skratky"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Vyhľadávacie odkazy"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Žiadne výsledky vyhľadávania"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zbalenia"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalenia"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"alebo"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto prechodu domov"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akčný kláves"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Skvelé!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejsť späť"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ak chcete prejsť späť, potiahnite kdekoľvek na touchpade troma prstami doľava alebo doprava.\n\nMôžete použiť aj klávesovú skratku, teda akčný kláves + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Prechod na plochu"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Na plochu môžete kedykoľvek prejsť potiahnutím troma prstami zdola obrazovky."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tri prsty na touchpade pohybujúce sa doprava a doľava"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Obrazovka zariadenia, na ktorej je animácia gesta späť"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. úroveň z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládanie domácnosti"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ak sa chcete vrátiť na plochu, potiahnite po touchpade troma prstami nahor."</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ak si chcete zobraziť nedávne aplikácie, potiahnite po touchpade troma prstami nahor a pridržte ich."</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ak si chcete zobraziť všetky aplikácie, stlačte na klávesnici akčný kláves"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Zamaskované"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Zobrazíte odomknutím"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Prechádzajte späť pomocou touchpadu"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Potiahnite troma prstami doľava alebo doprava. Viac o gestách sa dozviete klepnutím."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Vráťte sa na plochu pomocou touchpadu"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Potiahnite troma prstami nahor a pridržte ich. Viac o gestách sa dozviete klepnutím."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazte si všetky aplikácie pomocou klávesnice"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Akčný kláves môžete stlačiť kedykoľvek. Viac o gestách sa dozviete klepnutím."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Mimoriadne stmavenie je teraz súčasťou posúvača na úpravu jasu"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Teraz môžete obrazovku mimoriadne stmaviť ešte ďalším znížením úrovne jasu v hornej časti obrazovky.\n\nNajlepšie to funguje v tmavom prostredí."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstrániť skratku mimoriadneho stmavenia"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Skratka mimoriadneho stmavenia bola odstránená. Ak chcete znížiť jas, použite bežný posúvač jasu."</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 69f63b99202c..170bfb23be63 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Snemalnik zaslona"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Želite začeti snemati?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Med snemanjem ima Android dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Med snemanjem aplikacije ima Android dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Začni snemanje"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snemanje zvoka"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvok v napravi"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvoki v napravi, kot so glasba, klici in toni zvonjenja."</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Pošlji"</string> <string name="cancel" msgid="1089011503403416730">"Prekliči"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logotip aplikacije"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Potrdite"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Poskusi znova"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Če želite preklicati preverjanje pristnosti, se dotaknite"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite za seznanitev nove naprave"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Prednastavljenih vrednosti ni bilo mogoče posodobiti"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Prednastavljeno"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Samodejni podnapisi"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Samodejni podnapisi"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite odblokirati mikrofon v napravi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite odblokirati fotoaparat v napravi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite odblokirati fotoaparat in mikrofon v napravi?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavitve"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Izklopljeno"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastavitev"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljanje v nastavitvah"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ni aktivnih načinov}=1{Način {mode} je aktiven}one{# način je aktiven}two{# načina sta aktivna}few{# načini so aktivni}other{# načinov je aktivnih}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov, opomnikov, dogodkov in klicateljev, ki jih določite. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ne bodo vas motili zvoki ali vibriranje, razen v primeru alarmov. Še vedno pa boste slišali vse, kar se boste odločili predvajati, vključno z glasbo, videoposnetki in igrami."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prilagodi"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Počasno polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Pripomočki na zaklenjenem zaslonu"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Pripomoček <xliff:g id="WIDGET_NAME">%1$s</xliff:g> je bil dodan na zaklenjeni zaslon"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Opusti"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Želite začeti snemati ali predvajati?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Storitev, ki zagotavlja to funkcijo, bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Celoten zaslon"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Posamezna aplikacija"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Deljenje ali snemanje aplikacije"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Želite začeti snemati ali predvajati z aplikacijo <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Pri deljenju, snemanju ali predvajanju ima aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Pri deljenju, snemanju ali predvajanju aplikacije ima aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začni"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite deliti zaslon z aplikacijo <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli eno aplikacijo"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli celoten zaslon"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri deljenju celotnega zaslona je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse na zaslonu. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri deljenju aplikacije je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse, kar je prikazano ali predvajano v tej aplikaciji. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli zaslon"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogočila to možnost"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite začeti predvajati?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Pri predvajanju ima Android dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Pri predvajanju aplikacije ima Android dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Začni predvajanje"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Želite predvajati vsebino zaslona?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Predvajanje vsebine ene aplikacije"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Predvajanje vsebine celotnega zaslona"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Pri predvajanju vsebine celotnega zaslona je vidno vse na zaslonu. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Pri predvajanju vsebine aplikacije je vidno vse, kar je prikazano ali predvajano v tej aplikaciji. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Predvajanje zaslona"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Želite začeti deliti?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Pri deljenju, snemanju ali predvajanju ima Android dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Pri deljenju, snemanju ali predvajanju aplikacije ima Android dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Začni"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Naprej"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Deljenje se začasno zaustavi ob preklopu aplikacije"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Delite to aplikacijo"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Preklopite nazaj"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Dostopnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Bližnjične tipke"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Bližnjice za iskanje"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ni rezultatov iskanja"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za strnitev"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za razširitev"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ali"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Poteza za začetni zaslon"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Gumb za dejanje"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Končano"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Odlično!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazaj"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sledilna ploščica s tremi prsti, ki se premikajo desno in levo"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Zaslon naprave z animacijo, ki prikazuje potezo za pomik nazaj"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Za pomik nazaj povlecite levo ali desno s tremi prsti kjer koli na sledilni ploščici.\n\nUporabite lahko tudi bližnjični tipki Action + ESC."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Odlično!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvedli ste potezo za pomik nazaj."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pomik na začetni zaslon"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Za pomik na začetni zaslon lahko kadar koli s tremi prsti povlečete navzgor z dna zaslona."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Odlično!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Izvedli ste potezo za pomik na začetni zaslon."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka za dejanja"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Za dostop do aplikacij pritisnite tipko za dejanja na tipkovnici."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Izvedli ste potezo za tipko za dejanja.\n\nČe hkrati pritisnete tipko za dejanja in poševnico naprej »/«, bodo prikazane vse razpoložljive bližnjice."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stopnja %1$d od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrolniki za dom"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Za pomik na začetni zaslon povlecite s tremi prsti navzgor po sledilni ploščici"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Za ogled nedavnih aplikacij povlecite s tremi prsti navzgor po sledilni ploščici in pridržite"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za ogled vseh aplikacij pritisnite tipko za dejanja na tipkovnici"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Zakrito"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Odklenite za ogled"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Uporaba sledilne ploščice za pomik nazaj"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"S tremi prsti povlecite levo ali desno. Dotaknite se, če želite spoznati več potez."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Uporaba sledilne ploščice za pomik na začetni zaslon"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"S tremi prsti povlecite navzgor in pridržite. Dotaknite se, če želite spoznati več potez."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Uporaba tipkovnice za prikaz vseh aplikacij"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kadar koli pritisnite tipko za dejanja. Dotaknite se, če želite spoznati več potez."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funkcija Zelo zatemnjeno je zdaj del vrstice za uravnavanje svetlosti"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Zdaj lahko zelo zatemnite zaslon tako, da na vrhu zaslona dodatno zmanjšate raven svetlosti.\n\nTa funkcija najbolje deluje v temnem okolju."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstrani bližnjico do funkcije Zelo zatemnjeno"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Bližnjica do funkcije Zelo zatemnjeno je odstranjena. Če želite zmanjšati svetlost, uporabite običajno vrstico za uravnavanje svetlosti."</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index b26c7d8b92ce..6dcc25677c8f 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Regjistruesi i ekranit"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Të niset regjistrimi?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Kur ti regjistron, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Kur ti regjistron një aplikacion, Android ka qasje te çdo gjë e dukshme ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesës, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Nis regjistrimin"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Regjistro audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audioja e pajisjes"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Tingulli nga pajisja, si muzika, telefonatat dhe tonet e ziles"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Dërgo"</string> <string name="cancel" msgid="1089011503403416730">"Anulo"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logoja e aplikacionit"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Konfirmo"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Provo përsëri"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Trokit për të anuluar vërtetimin"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliko për të çiftuar një pajisje të re"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Paravendosja nuk mund të përditësohej"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Paravendosja"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Titra në çast"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Titra në çast"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Të zhbllokohet mikrofoni i pajisjes?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Të zhbllokohet kamera e pajisjes?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Të zhbllokohen kamera dhe mikrofoni i pajisjes?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cilësimet"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Joaktiv"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfiguro"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Menaxho te cilësimet"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nuk ka modalitete aktive}=1{\"{mode}\" është aktiv}other{# modalitete janë aktive}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve, alarmeve rikujtuese, ngjarjeve dhe telefonuesve që specifikon. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nuk do të shqetësohesh nga tingujt dhe dridhjet, përveç alarmeve. Do të vazhdosh të dëgjosh çdo gjë që zgjedh të luash duke përfshirë muzikën, videot dhe lojërat."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizo"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Miniaplikacionet në ekranin e kyçjes"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Miniaplikacioni i <xliff:g id="WIDGET_NAME">%1$s</xliff:g> u shtua tek ekrani i kyçjes"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hiq"</string> @@ -506,10 +510,10 @@ <string name="accessibility_action_label_select_widget" msgid="8897281501387398191">"zgjidh miniaplikacionin"</string> <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"hiq miniaplikacionin"</string> <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"vendos miniaplikacionin e zgjedhur"</string> - <string name="communal_widget_picker_title" msgid="1953369090475731663">"Kyç miniaplikacionet e ekranit"</string> + <string name="communal_widget_picker_title" msgid="1953369090475731663">"Miniaplikacionet në ekranin e kyçjes"</string> <string name="communal_widget_picker_description" msgid="490515450110487871">"Çdo person mund të shikojë miniaplikacionet në ekranin tënd të kyçjes, edhe nëse tableti është i kyçur."</string> <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"anulo zgjedhjen e miniaplikacionit"</string> - <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Kyç miniaplikacionet e ekranit"</string> + <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Miniaplikacionet në ekranin e kyçjes"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Për të hapur një aplikacion duke përdorur një miniaplikacion, do të duhet të verifikosh që je ti. Ki parasysh gjithashtu që çdo person mund t\'i shikojë, edhe kur tableti yt është i kyçur. Disa miniaplikacione mund të mos jenë planifikuar për ekranin tënd të kyçjes dhe mund të mos jetë e sigurt t\'i shtosh këtu."</string> <string name="communal_widgets_disclaimer_button" msgid="4423059765740780753">"E kuptova"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Ndërro përdorues"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione, si p.sh.: fjalëkalimet, detajet e pagesave, fotografitë, mesazhet, si dhe audion që luan ti."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Të niset regjistrimi ose transmetimi?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Shërbimi që e ofron këtë funksion do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione, si p.sh.: fjalëkalimet, detajet e pagesave, fotografitë, mesazhet, si dhe audion që luan ti."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Të gjithë ekranin"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Vetëm një aplikacion"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Ndaj ose regjistro një aplikacion"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Të niset regjistrimi ose transmetimi me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kur ti ndan, regjistron ose transmeton, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kur ti ndan, regjistron ose transmeton një aplikacion, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Nis"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Të ndahet ekrani yt me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ndaj një aplikacion"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ndaj të gjithë ekranin"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kur ti ndan të gjithë ekranin, çdo gjë në ekranin tënd është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kur ti ndan një aplikacion, çdo gjë që shfaqet ose luhet në atë aplikacion është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ndaj ekranin"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> e ka çaktivizuar këtë opsion"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Të niset transmetimi?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kur ti transmeton, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kur ti transmeton një aplikacion, Android ka qasje te çdo gjë e dukshme ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesës, mesazhet, fotografitë, si dhe audion dhe videon."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Nis transmetimin"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Të transmetohet ekrani yt?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Transmeto një aplikacion"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Transmeto të gjithë ekranin"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kur ti transmeton të gjithë ekranin, çdo gjë në ekranin tënd është e dukshme. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kur ti transmeton një aplikacion, çdo gjë që shfaqet ose luhet në atë aplikacion është e dukshme. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Transmeto ekranin"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Të niset ndarja?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kur ti ndan, regjistron ose transmeton, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kur ti ndan, regjistron ose transmeton një aplikacion, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Nis"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Para"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Ndarja vendoset në pauzë kur ndërron aplikacionet"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Ndaj më mirë këtë aplikacion"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Kthehu përsëri"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Qasshmëria"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Shkurtoret e tastierës"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Kërko për shkurtoret"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Asnjë rezultat kërkimi"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona e palosjes"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona e zgjerimit"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ose"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gjesti për të shkuar tek ekrani bazë"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasti i veprimit"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"U krye"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Punë e shkëlqyer!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kthehu prapa"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Për t\'u kthyer, rrëshqit shpejt majtas ose djathtas duke përdorur tri gishta kudo në bllokun me prekje.\n\nPër ta bërë këtë, mund të përdorësh gjithashtu shkurtoren e tastierës \"Action + ESC\"."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Shko tek ekrani bazë"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Për të shkuar tek ekrani bazë në çdo kohë, rrëshqit shpejt lart me tre gishta nga fundi i ekranit."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Blloku me prekje që tregon tre gishta që lëvizin djathtas dhe majtas"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Ekrani i pajisjes që tregon një animacion për gjestin e kthimit prapa"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Drita e sfondit e tastierës"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveli: %1$d nga %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrollet e shtëpisë"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Për të shkuar tek ekrani bazë, rrëshqit shpejt lart me tre gishta në bllokun me prekje"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Për aplikacionet e fundit, rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Për të shikuar të gjitha aplikacionet, shtyp tastin e veprimit në tastierë"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redaktuar"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Shkyçe për ta parë"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Përdor bllokun me prekje për t\'u kthyer prapa"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta. Trokit për të mësuar më shumë gjeste."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Përdor bllokun me prekje për të shkuar tek ekrani bazë"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta. Trokit për të mësuar më shumë gjeste."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Përdor tastierën për të shikuar të gjitha aplikacionet"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Shtyp tastin e veprimit në çdo kohë. Trokit për të mësuar më shumë gjeste."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Modaliteti \"Shumë më i zbehtë\" tani është pjesë e shiritit të ndriçimit"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Tani mund ta bësh ekranin shumë më të zbehtë duke e ulur nivelin e ndriçimit edhe më tej nga kreu i ekranit.\n\nKjo funksionon më mirë kur je në një mjedis të errët."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Hiq shkurtoren e modalitetit \"Shumë më i zbehtë\""</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Shkurtorja e modalitetit \"Shumë më i zbehtë\" u hoq. Për të ulur ndriçimin, përdor shiritin e zakonshëm të ndriçimit."</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 7acfbf5f403e..304fbdba3d7b 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Снимач екрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Желите да започнете снимање?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају док снимате. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Када снимате апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Започни снимање"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Снимај звук"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук уређаја"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук са уређаја, на пример, музика, позиви и мелодије звона"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Пошаљи"</string> <string name="cancel" msgid="1089011503403416730">"Откажи"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Логотип апликације"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Потврди"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Пробај поново"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Додирните да бисте отказали потврду идентитета"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликните да бисте упарили нов уређај"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ажурирање задатих подешавања није успело"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Унапред одређена подешавања"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Титл уживо"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Титл уживо"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Желите да одблокирате микрофон уређаја?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Желите да одблокирате камеру уређаја?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Желите да одблокирате камеру и микрофон уређаја?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Подешавања"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Искључено"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Подеси"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Управљајте у подешавањима"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Нема активних режима}=1{Активан је {mode} режим}one{Активан је # режим}few{Активна су # режима}other{Активно је # режима}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Неће вас узнемиравати звукови и вибрације осим за аларме, подсетнике, догађаје и позиваоце које наведете. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Неће вас узнемиравати звукови и вибрације осим за аларме. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Прилагоди"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Споро се пуни • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Виџети на закључаном екрану"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> је додат на закључани екран"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Прилагодите"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Одбаци"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Желите да почнете снимање или пребацивање?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услуга која пружа ову функцију ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Цео екран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Једна апликација"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Делите или снимите апликацију"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Желите да почнете снимање или пребацивање помоћу апликације <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Када делите, снимате или пребацујете, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Када делите, снимате или пребацујете апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Покрени"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Желите да делите екран са апликацијом <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Дели једну апликацију"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дели цео екран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Када делите цео екран, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види све што је на њему. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Када делите апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види сав садржај који се приказује или пушта у њој. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дели екран"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је онемогућила ову опцију"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Желите да започнете пребацивање?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Када пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Када пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Започни пребацивање"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Желите да пребаците екран?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Пребаци једну апликацију"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Пребаци цео екран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Када пребацујете цео екран, види се све што је на њему. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Када пребацујете апликацију, види се сав садржај који се приказује или пушта у њој. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Пребацивање екрана"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Желите да почнете да делите?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Када делите, снимате или пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Када делите, снимате или пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато пазите на лозинке, информације о плаћању, поруке, слике, и аудио и видео садржај."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Покрени"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Даље"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Дељење се зауставља када мењате апликације"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Дели ову апликацију"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Врати"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Приступачност"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Тастерске пречице"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Пречице претраге"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Нема резултата претраге"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за скупљање"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширивање"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Покрет за почетну страницу"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тастер радњи"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Одлично!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Да бисте се вратили, превуците улево са три прста било где на тачпеду.\n\nМожете да користите и тастерску пречицу Alt + ESC за ово."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Иди на почетни екран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Да бисте отишли на почетни екран у било ком тренутку, превуците нагоре од дна екрана помоћу три прста."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Тачпед са приказом три прста који се померају удесно и улево"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран уређаја са приказом анимације покрета за назад"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Позадинско осветљење тастатуре"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. ниво од %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроле за дом"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Да бисте отишли на почетни екран, превуците нагоре са три прста на тачпеду"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Да бисте прегледали недавне апликације, превуците нагоре и задржите са три прста на тачпеду"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Да бисте погледали све апликације, притисните тастер радњи на тастатури"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Редиговано"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Откључајте за приказ"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Користите тачпед да бисте се вратили"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Превуците улево или удесно са три прста. Додирните да бисте видели више покрета."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Користите тачпед да бисте отишли на почетни екран"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Превуците нагоре и задржите са три прста. Додирните да бисте видели више покрета."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Користите тастатуру да бисте прегледали све апликације"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Притисните тастер радњи у било ком тренутку. Додирните да бисте видели више покрета."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Додатно затамњивање је сада део траке за осветљеност"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Сада можете додатно да затамните екран смањивањем нивоа осветљености при врху екрана. \n\nОво најбоље функционише када сте у тамном окружењу."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Уклони пречицу за додатно затамњивање"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Уклоњена је пречица за додатно затамњивање. Да бисте смањили осветљеност, користите уобичајену траку за осветљеност."</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index b632dde15227..f79aa3a42063 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Skärminspelare"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Vill du starta inspelningen?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"När du spelar in har Android åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"När du spelar in en app har Android åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Börja spela in"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Spela in ljud"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Ljud på enheten"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Ljud från enheten, till exempel musik, samtal och ringsignaler"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Skicka"</string> <string name="cancel" msgid="1089011503403416730">"Avbryt"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Appens logotyp"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Bekräfta"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Försök igen"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tryck för att avbryta autentiseringen"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Klicka för att parkoppla en ny enhet"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Det gick inte att uppdatera förinställningen"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Förinställning"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Live Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vill du återaktivera enhetens mikrofon?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vill du återaktivera enhetens kamera?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vill du återaktivera enhetens kamera och mikrofon?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Inställningar"</string> <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Ställ in"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Hantera i inställningarna"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Inga aktiva lägen}=1{{mode} är aktivt}other{# lägen är aktiva}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Du blir inte störd av ljud och vibrationer, förutom från alarm, påminnelser, händelser och specifika samtal. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Du blir inte störd av ljud och vibrationer, förutom från alarm. Ljudet är fortfarande på för sådant du väljer att spela upp, till exempel musik, videor och spel."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Anpassa"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas långsamt • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Widgetar på låsskärmen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Widgeten <xliff:g id="WIDGET_NAME">%1$s</xliff:g> har lagts till på låsskärmen"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassa"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorera"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar till exempel lösenord, betalningsuppgifter, foton, meddelanden och ljud som du spelar upp."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Vill du börja spela in eller casta?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Den tjänst som tillhandahåller funktionen får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar till exempel lösenord, betalningsuppgifter, foton, meddelanden och ljud som du spelar upp."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Hela skärmen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"En enda app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Dela eller spela in en app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Vill du börja spela in eller casta med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"När du delar, spelar in eller castar har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"När du delar, spelar in eller castar en app har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Börja"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vill du dela skärmen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dela en app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dela hela skärmen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"När du delar hela skärmen är allt på skärmen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"När du delar en app är allt som visas eller spelas upp i appen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dela skärmen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inaktiverat alternativet"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vill du börja casta?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"När du castar har Android åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"När du castar en app har Android åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Börja casta"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Vill du casta skärmen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Casta en app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Casta hela skärmen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"När du castar hela skärmen är allt på skärmen synligt. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"När du castar en app är allt som visas eller spelas i den appen synligt. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Casta skärmen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Vill du börja dela?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"När du delar, spelar in eller castar har Android åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"När du delar, spelar in eller castar en app har Android åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Börja"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Nästa"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Delningen pausas när du byter appar"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Dela den här appen i stället"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Byt tillbaka"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Tillgänglighet"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Kortkommandon"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Sökgenvägar"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Inga sökresultat"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikonen Komprimera"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikonen Utöka"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Rörelse för att öppna startskärmen"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Åtgärdstangent"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klar"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Bra jobbat!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tillbaka"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Gå tillbaka genom att svepa åt vänster eller höger med tre fingrar var som helst på styrplattan.\n\nDu kan även använda kortkommandot Åtgärd + Esc."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Återvänd till startskärmen"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Öppna startskärmen när som helst genom att svepa uppåt med tre fingrar från skärmens nederkant."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Tre fingrar rör sig åt höger och vänster på en styrplatta"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"En enhetsskärm visar en animation för rörelsen Tillbaka"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hemstyrning"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Svep uppåt på styrplattan med tre fingrar för att gå till startskärmen"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Svep uppåt på styrplattan med tre fingrar och håll kvar för att se nyligen använda appar"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tryck på åtgärdstangenten på tangentbordet för att se alla appar"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Anonymiserad"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås upp för att visa"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Använd styrplattan för att gå tillbaka"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Svep åt vänster eller höger med tre fingrar. Tryck för att lära dig fler rörelser."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Använd styrplattan för att gå till startskärmen"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Svep uppåt med tre fingrar och håll kvar. Tryck för att lära dig fler rörelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Använd tangentbordet för att se alla appar"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryck på åtgärdstangenten när som helst. Tryck för att lära dig fler rörelser."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extradimmat är nu en del av fältet för ljusstyrka"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nu kan du göra skärmen extradimmad genom att sänka ljusstyrkan ännu mer från överst på skärmen.\n\nDetta fungerar bäst när omgivningen är mörk."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ta bort kortkommandot för extradimmat"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kortkommandot för extradimmat har tagits bort. Använd det vanliga fältet för ljusstyrka om du vill sänka ljusstyrkan."</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index d3e4e5d21e98..8d944c6ea6f0 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Kinasa Skrini"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Ungependa kuanza kurekodi?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Unaporekodi, Android inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Unaporekodi programu, Android inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Anza kurekodi"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Rekodi sauti"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Sauti ya kifaa"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sauti kutoka kwenye kifaa chako, kama vile muziki, simu na milio ya simu"</string> @@ -134,7 +144,7 @@ <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Ungependa kuacha kuonyesha skrini?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Kwa sasa unatuma maudhui yaliyo katika skrini yako nzima kwenye programu"</string> - <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unatumia <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g> pamoja na wengine"</string> + <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Kwa sasa unaonyesha <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Kwa sasa unatumia programu pamoja na wengine"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Acha kuonyesha skrini"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"Inatuma skrini"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Tuma"</string> <string name="cancel" msgid="1089011503403416730">"Ghairi"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Nembo ya programu"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Thibitisha"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Jaribu tena"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Gusa ili ughairi uthibitishaji"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Bofya ili uunganishe kifaa kipya"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Imeshindwa kusasisha mipangilio iliyowekwa mapema"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Mipangilio iliyowekwa mapema"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Manukuu Papo Hapo"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Manukuu Papo Hapo"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Ungependa kuwacha kuzuia maikrofoni ya kifaa?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Ungependa kuacha kuzuia kamera ya kifaa?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Ungependa kuwacha kuzuia kamera na maikrofoni ya kifaa?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mipangilio"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Imezimwa"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Weka mipangilio"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Dhibiti katika mipangilio"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Hakuna hali za kutumika}=1{Unatumia {mode}}other{Unatumia hali #}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele, vikumbusho, matukio na simu zinazopigwa na watu uliobainisha. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Hutasumbuliwa na sauti na mitetemo, isipokuwa kengele. Bado utasikia chochote utakachochagua kucheza, ikiwa ni pamoja na muziki, video na michezo."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Badilisha upendavyo"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji polepole • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Wijeti kwenye skrini iliyofungwa"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g> imewekwa kwenye skrini iliyofungwa"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Weka mapendeleo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Funga"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Ungependa kuanza kurekodi au kutuma?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Huduma inayotoa utendaji huu itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Skrini nzima"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Programu moja"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Shiriki au rekodi programu"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Ungependa kuanza kurekodi au kutuma ukitumia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Unaposhiriki, kurekodi au kutuma, programu ya <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Unaposhiriki, kurekodi au kutuma programu, programu, programu ya <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Anza"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ungependa kuruhusu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ifikie skrini yako?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ruhusu ufikiaji wa programu moja"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ruhusu ufikiaji wa skrini nzima"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Unaporuhusu ufikiaji wa skrini nzima, chochote kilicho katika skrini yako kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Unaporuhusu ufikiaji wa programu, chochote kinachoonyeshwa au kuchezwa katika programu hiyo kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ruhusu ufikiaji wa skrini"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezima chaguo hili"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Ungependa kuanza kutuma?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Unapotuma, Android inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Unapotuma programu, Android inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Anza kutuma"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Ungependa kutuma maudhui yaliyo katika skrini yako?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Tuma maudhui ya programu moja"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Tuma maudhui katika skrini nzima"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Unapotuma maudhui katika skrini yako nzima, chochote kilicho kwenye skrini yako kitaonekana. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Unapotuma maudhui ya programu moja, chochote kinachoonekana au kucheza katika programu hiyo kitaonekana. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Tuma skrini"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Ungependa kuanza kushiriki?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Unaposhiriki, kurekodi au kutuma, Android inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Unaposhiriki, kurekodi au kutuma programu, Android inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Anza"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Endelea"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Itasitisha kushiriki unapobadilisha programu"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Shiriki programu hii badala yake"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Rejea"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Ufikivu"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Mikato ya kibodi"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Njia mkato za kutafutia"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Hamna matokeo ya utafutaji"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kunja aikoni"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Panua aikoni"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"au"</string> @@ -1383,23 +1396,37 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Mguso wa kurudi kwenye skrini ya kwanza"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kitufe cha vitendo"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Nimemaliza"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Kazi nzuri!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Rudi nyuma"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Telezesha vidole vitatu kushoto au kulia mahali popote kwenye padi ya kugusa ili urudi nyuma.\n\nUnaweza pia kutumia mikato ya kibodi ya Kitendo pamoja na ESC kutekeleza kitendo hiki."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Nenda kwenye skrini ya kwanza"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ili uende kwenye skrini ya kwanza wakati wowote, telezesha vidole vitatu juu kutoka sehemu ya chini ya skrini yako."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Padi ya kugusa inayoonyesha vidole vitatu vikisonga kulia na kushoto"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Skrini ya kifaa inayoonyesha uhuishaji wa mguso wa nyuma"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Kiwango cha %1$d kati ya %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Dhibiti Vifaa Nyumbani"</string> <string name="home_controls_dream_description" msgid="4644150952104035789">"Fikia haraka vidhibiti vya vifaa nyumbani vikiwa taswira ya skrini"</string> <string name="volume_undo_action" msgid="5815519725211877114">"Tendua"</string> - <string name="back_edu_toast_content" msgid="4530314597378982956">"Telezesha vidole vitatu kutoka kushoto au kulia kwenye padi ya kugusa ili urudi nyuma"</string> + <string name="back_edu_toast_content" msgid="4530314597378982956">"Telezesha vidole vitatu kushoto au kulia kwenye padi ya kugusa ili urudi nyuma"</string> <string name="home_edu_toast_content" msgid="3381071147871955415">"Telezesha vidole vitatu juu kwenye padi ya kugusa ili urudi kwenye skrini ya kwanza"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Telezesha vidole vitatu juu na ushikilie kwenye padi ya kugusa ili uangalie programu za hivi majuzi"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bonyeza kitufe cha vitendo kwenye kibodi yako ili uangalie programu zako zote"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Maandishi yameondolewa"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Fungua ili uone"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Kutumia padi yako ya kugusa ili kurudi nyuma"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Telezesha vidole vitatu kulia au kushoto. Gusa ili upate maelezo kuhusu miguso zaidi."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Kutumia padi yako ya kugusa ili kurudi kwenye skrini ya kwanza"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Telezesha vidole vitatu juu na ushikilie. Gusa ili upate maelezo kuhusu miguso zaidi."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kutumia kibodi yako kuangalia programu zote"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bonyeza kitufe cha vitendo wakati wowote. Gusa ili upate maelezo kuhusu miguso zaidi."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Kipunguza mwangaza zaidi sasa ni sehemu ya upau wa mwangaza"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sasa unaweza kupunguza mwangaza zaidi kwa kupunguza kabisa kiwango cha mwangaza katika sehemu ya juu ya skrini yako.\n\nMipangilio hii hufanya kazi vyema zaidi ukiwa katika mazingira yenye giza."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ondoa njia ya mkato ya kipunguza mwangaza zaidi"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Njia ya mkato ya kipunguza mwangaza zaidi imeondolewa. Tumia upau wa kawaida wa mwangaza ili upunguze mwangaza wako."</string> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 6cef518d194f..9fed333601c1 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"ஸ்கிரீன் ரெக்கார்டர்"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ரெக்கார்டு செய்யத் தொடங்கவா?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"நீங்கள் ரெக்கார்டு செய்யும்போது உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ஓர் ஆப்ஸை நீங்கள் ரெக்கார்டு செய்யும்போது அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ரெக்கார்டு செய்யத் தொடங்கு"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ஆடியோவை ரெக்கார்டு செய்"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"சாதன ஆடியோ"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"இசை, அழைப்புகள், ரிங்டோன்கள் போன்ற உங்கள் சாதனத்திலிருந்து வரும் ஒலி"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"அனுப்பு"</string> <string name="cancel" msgid="1089011503403416730">"ரத்துசெய்"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ஆப்ஸ் லோகோ"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"உறுதிப்படுத்துக"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"மீண்டும் முயல்க"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"பயோமெட்ரிக் அடையாளத்தை ரத்துசெய்ய தட்டவும்"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"புதிய சாதனத்தை இணைக்க கிளிக் செய்யலாம்"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"முன்னமைவைப் புதுப்பிக்க முடியவில்லை"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"முன்னமைவு"</string> - <string name="live_caption_title" msgid="8916875614623730005">"உடனடி வசன உரை"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"உடனடி வசன உரை"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"சாதனத்தின் மைக்ரோஃபோனுக்கான தடுப்பை நீக்கவா?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"சாதனத்தின் கேமராவுக்கான தடுப்பை நீக்கவா?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"சாதனத்தின் கேமராவுக்கும் மைக்ரோஃபோனுக்குமான தடுப்பை நீக்கவா?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"அமைப்புகள்"</string> <string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string> <string name="zen_mode_off" msgid="1736604456618147306">"முடக்கப்பட்டுள்ளது"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"அமையுங்கள்"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"அமைப்புகளில் நிர்வகியுங்கள்"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{செயலிலுள்ள பயன்முறைகள் எதுவுமில்லை}=1{{mode} செயலில் உள்ளது}other{# பயன்முறைகள் செயலில் உள்ளன}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"அலாரங்கள், நினைவூட்டல்கள், நிகழ்வுகள் மற்றும் குறிப்பிட்ட அழைப்பாளர்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"அலாரங்களைத் தவிர்த்து, பிற ஒலிகள் மற்றும் அதிர்வுகளின் தொந்தரவு இருக்காது. எனினும், நீங்கள் எதையேனும் (இசை, வீடியோக்கள், கேம்ஸ் போன்றவை) ஒலிக்கும்படி தேர்ந்தெடுத்திருந்தால், அவை வழக்கம் போல் ஒலிக்கும்."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"பிரத்தியேகமாக்கு"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • மெதுவாக சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுதும் சார்ஜாகும்"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"பூட்டுத் திரையில் விட்ஜெட்கள்"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"பூட்டுத் திரையில் <xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட் சேர்க்கப்பட்டது"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"பிரத்தியேகமாக்குங்கள்"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"மூடுக"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது உங்கள் சாதனத்திலிருந்து பிளே செய்யப்படுகின்ற அனைத்துத் தகவல்களுக்குமான அணுகலை <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸ் கொண்டிருக்கும். கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்றவை இதிலடங்கும்."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ரெக்கார்டு செய்ய அல்லது அலைபரப்பத் தொடங்கவா?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்திலிருந்து பிளே செய்யப்படுகின்ற அனைத்துத் தகவல்களையும் இந்தச் செயல்பாட்டை வழங்கும் சேவையால் அணுக முடியும். கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்றவை இதிலடங்கும்."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"முழுத்திரையையும்"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"ஓர் ஆப்ஸ்"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ஆப்ஸைப் பகிர்தல் அல்லது ரெக்கார்டு செய்தல்"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸ் மூலம் ரெக்கார்டு செய்ய அல்லது அலைபரப்பத் தொடங்கவா?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"நீங்கள் ஓர் ஆப்ஸைப் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"தொடங்கு"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> உடன் திரையைப் பகிரவா?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ஓர் ஆப்ஸைப் பகிர்"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"முழுத் திரையையும் பகிர்"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"உங்கள் முழுத்திரையையும் பகிரும்போது, திரையில் உள்ள அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ஓர் ஆப்ஸைப் பகிரும்போது, அதில் காட்டப்படும்/பிளே செய்யப்படும் அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"திரையைப் பகிர்"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இந்த விருப்பத்தை முடக்கியுள்ளது"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"அலைபரப்பைத் தொடங்கவா?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"நீங்கள் அலைபரப்பும்போது உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ஓர் ஆப்ஸை நீங்கள் அலைபரப்பும்போது அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"அலைபரப்பைத் தொடங்கு"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"உங்கள் திரையை அலைபரப்ப வேண்டுமா?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ஓர் ஆப்ஸை அலைபரப்பு"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"முழுத்திரையையும் அலைபரப்பு"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"உங்கள் முழுத்திரையையும் அலைபரப்பும்போது திரையில் உள்ள அனைத்தையும் பார்க்க முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"ஓர் ஆப்ஸை அலைபரப்பும்போது அதில் காட்டப்படுகின்ற அல்லது அதில் பிளே செய்யப்படுகின்ற அனைத்தையும் பார்க்க முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"திரையை அலைபரப்பு"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"பகிர்தலைத் தொடங்கவா?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"நீங்கள் ஓர் ஆப்ஸைப் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"தொடங்கு"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"அடுத்து"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"பகிர்தல் ஆப்ஸிற்கு இடையே மாறும்போது இடைநிறுத்தப்படும்"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"அதற்குப் பதிலாக இந்த ஆப்ஸைப் பகிர்"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"முந்தையதற்கு மாறு"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"மாற்றுத்திறன் வசதி"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"கீபோர்டு ஷார்ட்கட்கள்"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"தேடல் ஷார்ட்கட்கள்"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"தேடல் முடிவுகள் இல்லை"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"சுருக்குவதற்கான ஐகான்"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"விரிவாக்குவதற்கான ஐகான்"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"அல்லது"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"முகப்பிற்குச் செல்வதற்கான சைகை"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ஆக்ஷன் பட்டன்"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"முடிந்தது"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"அருமை!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"பின்செல்"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"பின்செல்ல, உங்கள் டச்பேடில் எங்கு வேண்டுமானாலும் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்.\n\nஇதற்கு நீங்கள் கீபோர்டு ஷார்ட்கட் செயல்பாடுகள் + Esc பட்டனையும் பயன்படுத்தலாம்."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"முகப்பிற்குச் செல்"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"எப்போது வேண்டுமானாலும் உங்கள் முகப்புத் திரைக்குச் செல்ல, மூன்று விரல்களால் திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யவும்."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"மூன்று விரல்கள் வலது மற்றும் இடதுபுறம் நகர்வதை டச்பேட் காட்டுகிறது"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"பின்செல்லும் சைகைக்கான அனிமேஷனை சாதனத்தின் திரை காட்டுகிறது"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"நிலை, %2$d இல் %1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ஹோம் கன்ட்ரோல்கள்"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"சமீபத்திய ஆப்ஸைப் பார்க்க, டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"அனைத்து ஆப்ஸையும் பார்க்க, உங்கள் கீபோர்டில் உள்ள ஆக்ஷன் பட்டனை அழுத்தவும்"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"அர்த்தம் புரியாதபடி திருத்தப்பட்டது"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"பார்ப்பதற்கு அன்லாக் செய்யவும்"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"பின்செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"மூன்று விரல்களால் இடது அல்லது வலதுபுறம் ஸ்வைப் செய்யவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"முகப்புக்குச் செல்ல, உங்கள் டச்பேடைப் பயன்படுத்துங்கள்"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"அனைத்து ஆப்ஸையும் பார்க்க உங்கள் கீபோர்டைப் பயன்படுத்துங்கள்"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"எப்போது வேண்டுமானாலும் ஆக்ஷன் பட்டனை அழுத்தலாம். சைகைகள் குறித்து மேலும் அறிய தட்டவும்."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"\'மிகக் குறைவான வெளிச்சம்\' அம்சம் இப்போது ஒளிர்வுப் பட்டியின் ஒரு பகுதியாகும்"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"இப்போது உங்கள் திரையின் மேற்பகுதியில் ஒளிர்வு அளவைக் குறைப்பதன் மூலம் திரையை மிகக் குறைவான வெளிச்சத்திற்குக் கொண்டு வரலாம்.\n\nஇருட்டான சூழலில் இருக்கும்போது இது சிறப்பாகச் செயல்படும்."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"மிகக் குறைவான வெளிச்சத்திற்கான ஷார்ட்கட்டை அகற்று"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"மிகக் குறைவான வெளிச்சத்திற்கான ஷார்ட்கட் அகற்றப்பட்டது. உங்கள் ஒளிர்வைக் குறைக்க, வழக்கமான ஒளிர்வுப் பட்டியைப் பயன்படுத்துங்கள்."</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index e9cb6ebc53cc..6c9896864d53 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"స్క్రీన్ రికార్డర్"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"రికార్డింగ్ను ప్రారంభించాలా?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"మీరు రికార్డ్ చేసేటప్పుడు, మీ స్క్రీన్పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"మీరు ఏదైనా యాప్ను రికార్డ్ చేసేటప్పుడు, ఆ యాప్లో చూపబడిన లేదా ప్లే అవుతున్న దేనినైనా Android యాక్సెస్ చేయగలదు. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"రికార్డింగ్ను ప్రారంభించండి"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ఆడియోను రికార్డ్ చేయండి"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"పరికరం ఆడియో"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే మ్యూజిక్, కాల్స్, రింగ్టోన్ల వంటి ధ్వనులు"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"పంపండి"</string> <string name="cancel" msgid="1089011503403416730">"రద్దు చేయండి"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"యాప్ లోగో"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"నిర్ధారించండి"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"మళ్లీ ట్రై చేయండి"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ప్రామాణీకరణను రద్దు చేయడానికి నొక్కండి"</string> @@ -390,7 +398,7 @@ <string name="thermal" msgid="6758074791325414831">"థర్మల్"</string> <string name="custom" msgid="3337456985275158299">"అనుకూలంగా మార్చుకోండి"</string> <string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"కస్టమ్ ట్రేస్ సెట్టింగ్లు"</string> - <string name="restore_default" msgid="5259420807486239755">"డిఫాల్ట్ను రీస్టోర్ చేయండి"</string> + <string name="restore_default" msgid="5259420807486239755">"ఆటోమేటిక్ సెట్టింగ్లకు రీస్టోర్ చేయండి"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"వన్-హ్యాండెడ్ మోడ్"</string> <string name="quick_settings_hearing_devices_label" msgid="7277170419679404129">"వినికిడి పరికరాలు"</string> <string name="quick_settings_hearing_devices_connected" msgid="6519069502397037781">"యాక్టివ్"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"కొత్త పరికరాన్ని పెయిర్ చేయడానికి క్లిక్ చేయండి"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ప్రీసెట్ను అప్డేట్ చేయడం సాధ్యపడలేదు"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ప్రీసెట్"</string> - <string name="live_caption_title" msgid="8916875614623730005">"లైవ్ క్యాప్షన్"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"లైవ్ క్యాప్షన్"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"పరికరంలోని కెమెరాను అన్బ్లాక్ చేయమంటారా?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"పరికరంలోని కెమెరా, మైక్రోఫోన్లను అన్బ్లాక్ చేయమంటారా?"</string> @@ -475,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తి ఛార్జ్"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"లాక్ స్క్రీన్లో విడ్జెట్లు"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్, లాక్ స్క్రీన్కు జోడించబడింది"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"కమ్యూనల్ ట్యుటోరియల్ను ప్రారంభించడానికి ఎడమ వైపునకు స్వైప్ చేయండి"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"అనుకూలంగా మార్చండి"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"విస్మరించండి"</string> @@ -528,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై కనిపించే సమాచారం లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏదైనా మీడియాకు సంబంధించిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్పై చూపబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్ను అందిస్తున్న సర్వీస్ యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ఫుల్-స్క్రీన్"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"సింగిల్ యాప్"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"యాప్ను షేర్ చేయండి లేదా రికార్డ్ చేయండి"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"మీరు షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"మీరు ఏదైనా యాప్ను షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఆ యాప్లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ప్రారంభించండి"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"మీ స్క్రీన్ను <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో షేర్ చేయండి?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ఒక యాప్ను షేర్ చేయండి"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"మొత్తం స్క్రీన్ను షేర్ చేయండి"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"మీ మొత్తం స్క్రీన్ను మీరు షేర్ చేసేటప్పుడు, మీ స్క్రీన్పై ఉన్నవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"మీరు యాప్ను షేర్ చేసేటప్పుడు, సంబంధిత యాప్లో కనిపించేవి లేదా ప్లే అయ్యేవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"స్క్రీన్ను షేర్ చేయండి"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ఈ ఆప్షన్ను డిజేబుల్ చేసింది"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ప్రసారాన్ని ప్రారంభించాలా?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"మీరు ప్రసారం చేసేటప్పుడు, మీ స్క్రీన్పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"మీరు ఏదైనా యాప్ను ప్రసారం చేసేటప్పుడు, ఆ యాప్లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"ప్రసారాన్ని ప్రారంభించండి"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"మీ స్క్రీన్ను ప్రసారం చేయాలా?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ఒక యాప్ను ప్రసారం చేయండి"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"మొత్తం స్క్రీన్ను ప్రసారం చేయండి"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"మీ స్క్రీన్ను మీరు ప్రసారం చేసేటప్పుడు, మీ స్క్రీన్పై ఉన్నవన్నీ కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"మీరు యాప్ను ప్రసారం చేసేటప్పుడు, సంబంధిత యాప్లో చూపబడేవన్నీ లేదా ప్లే అయ్యేవన్నీ కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"స్క్రీన్ను ప్రసారం చేయండి"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"షేర్ చేయడాన్ని ప్రారంభించాలా?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"మీరు షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"మీరు ఏదైనా యాప్ను షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఆ యాప్లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ప్రారంభించండి"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"తర్వాత"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"మీరు యాప్లను మార్చినప్పుడు షేరింగ్ పాజ్ చేయబడుతుంది"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"బదులుగా ఈ యాప్ను షేర్ చేయండి"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"మునుపటి దానికి స్విచ్ అవ్వండి"</string> @@ -1373,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"యాక్సెసిబిలిటీ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"కీబోర్డ్ షార్ట్కట్లు"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"సెర్చ్ షార్ట్కట్లు"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"సెర్చ్ ఫలితాలు ఏవీ లేవు"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"కుదించండి చిహ్నం"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"విస్తరించండి చిహ్నం"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"లేదా"</string> @@ -1380,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"హోమ్కు పంపే సంజ్ఞ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"యాక్షన్ కీ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"పూర్తయింది"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"విజయవంతమైంది!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"వెనుకకు"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"మూడు వేళ్లు కుడి, ఎడమకు కదులుతున్నట్లు చూపే టచ్ప్యాడ్"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"వెనుక సంజ్ఞ కోసం యానిమేషన్ను చూపుతున్న పరికర స్క్రీన్"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో ఎక్కడైనా మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడి వైపునకు స్వైప్ చేయండి.\n\nమీరు దీని కోసం + ESC కీబోర్డ్ షార్ట్కట్ యాక్షన్ను కూడా ఉపయోగించవచ్చు."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"చక్కగా పూర్తి చేశారు!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"తిరిగి వెనుకకు వెళ్ళడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్ను మీరు పూర్తి చేశారు."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"మొదటి ట్యాబ్కు వెళ్లండి"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ఏ సమయంలోనైనా మీ మొదటి స్క్రీన్కు వెళ్లడానికి, మీ స్క్రీన్ కింది నుండి మూడు వేళ్లతో పైకి స్వైప్ చేయండి."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"సూపర్!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"మొదటి స్క్రీన్కు వెళ్ళడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్ను మీరు పూర్తి చేశారు."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"యాక్షన్ కీ"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"మీ యాప్లను యాక్సెస్ చేయడానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి."</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"అభినందనలు!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"మీరు \'యాక్షన్ కీ\' సంజ్ఞను పూర్తి చేశారు.\n\nAction + / నొక్కితే, మీకు అందుబాటులో ఉండే షార్ట్కట్లన్నీ కనిపిస్తాయి."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్లైట్"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dలో %1$dవ స్థాయి"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"హోమ్ కంట్రోల్స్"</string> @@ -1397,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"హోమ్కు వెళ్లడానికి, టచ్ప్యాడ్లో మీ మూడు వెళ్లతో పైకి స్వైప్ చేయండి"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"ఇటీవలి యాప్లను చూడటానికి, టచ్ప్యాడ్లో మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"మీ యాప్లన్నింటినీ చూడటానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"దాచిపెట్టినది"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"చూడటానికి అన్లాక్ చేయండి"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"వెనుకకు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"మూడు వేళ్లతో ఎడమ / కుడి వైపునకు స్వైప్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"హోమ్కు వెళ్లడానికి మీ టచ్ప్యాడ్ను ఉపయోగించండి"</string> @@ -1405,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"మూడు వేళ్లతో పైకి స్వైప్ చేసి, హోల్డ్ చేయండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"యాప్లన్నింటినీ చూడటానికి మీ కీబోర్డ్ను ఉపయోగించండి"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ఏ సమయంలోనైనా యాక్షన్ కీని నొక్కండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"కాంతిని మరింత డిమ్ చేసే ఫీచర్ ఇప్పుడు బ్రైట్నెస్ బార్లో ఒక భాగం"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"మీరు ఇప్పుడు మీ స్క్రీన్ పైభాగం నుండి బ్రైట్నెస్ స్థాయిని తగ్గించడం ద్వారా కూడా స్క్రీన్ కాంతిని మరింత డిమ్ చేయవచ్చు.\n\nమీరు డార్క్ ఎన్విరాన్మెంట్లో ఉన్నప్పుడు కూడా ఇది బాగా పని చేస్తుంది."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్ను తీసివేయండి"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్ తీసివేయబడింది. మీ బ్రైట్నెస్ను తగ్గించడానికి, సాధారణ బ్రైట్నెస్ బార్ను ఉపయోగించండి."</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 0d131ac7279e..355dd381d6cd 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"โปรแกรมบันทึกหน้าจอ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"เริ่มบันทึกเลยไหม"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ขณะกำลังบันทึก Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"ขณะกำลังบันทึกแอป Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"เริ่มบันทึก"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"บันทึกเสียง"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"เสียงจากอุปกรณ์"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"เสียงจากอุปกรณ์ เช่น เพลง การโทร และเสียงเรียกเข้า"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"ส่ง"</string> <string name="cancel" msgid="1089011503403416730">"ยกเลิก"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"โลโก้แอป"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"ยืนยัน"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"ลองอีกครั้ง"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"แตะเพื่อยกเลิกการตรวจสอบสิทธิ์"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"คลิกเพื่อจับคู่อุปกรณ์ใหม่"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"ไม่สามารถอัปเดตค่าที่กำหนดล่วงหน้า"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ค่าที่กำหนดล่วงหน้า"</string> - <string name="live_caption_title" msgid="8916875614623730005">"คำบรรยายสด"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"คำบรรยายสด"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"เลิกบล็อกไมโครโฟนของอุปกรณ์ใช่ไหม"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"เลิกบล็อกกล้องของอุปกรณ์ใช่ไหม"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"เลิกบล็อกกล้องและไมโครโฟนของอุปกรณ์ใช่ไหม"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"การตั้งค่า"</string> <string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ปิด"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"ตั้งค่า"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"จัดการในการตั้งค่า"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ไม่มีโหมดที่ใช้งานอยู่}=1{ใช้งานอยู่ {mode} โหมด}other{ใช้งานอยู่ # โหมด}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก การช่วยเตือน กิจกรรม และผู้โทรที่ระบุไว้ คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"คุณจะไม่ถูกรบกวนจากเสียงและการสั่น ยกเว้นเสียงนาฬิกาปลุก คุณจะยังคงได้ยินสิ่งที่คุณเลือกเล่น เช่น เพลง วิดีโอ และเกม"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"กำหนดค่า"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จอย่างช้าๆ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"วิดเจ็ตในหน้าจอล็อก"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"เพิ่มวิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ในหน้าจอล็อกแล้ว"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ปรับแต่ง"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ปิด"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"เริ่มบันทึกหรือแคสต์เลยไหม"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"บริการที่มีฟังก์ชันนี้จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"ทั้งหน้าจอ"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"แอปเดียว"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"แชร์หรือบันทึกแอป"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"เริ่มบันทึกหรือแคสต์ด้วย <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> เลยไหม"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"เมื่อกำลังแชร์ บันทึก หรือแคสต์ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"เมื่อกำลังแชร์ บันทึก หรือแคสต์แอป <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"เริ่ม"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"แชร์หน้าจอกับ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ไหม"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"แชร์แอปเดียว"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"แชร์ทั้งหน้าจอ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"เมื่อกำลังแชร์ทั้งหน้าจอ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่อยู่บนหน้าจอ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"เมื่อกำลังแชร์แอป <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"แชร์หน้าจอ"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ปิดใช้ตัวเลือกนี้"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"เริ่มแคสต์เลยไหม"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"เมื่อกำลังแคสต์ Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"เมื่อกำลังแคสต์แอป Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"เริ่มแคสต์"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"แคสต์หน้าจอของคุณไหม"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"แคสต์แอปเดียว"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"แคสต์ทั้งหน้าจอ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"เมื่อกำลังแคสต์ทั้งหน้าจอ ทุกสิ่งที่อยู่บนหน้าจอจะมองเห็นได้ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"เมื่อกำลังแคสต์แอป ทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าวจะมองเห็นได้ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"แคสต์หน้าจอ"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"เริ่มแชร์เลยไหม"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"เมื่อกำลังแชร์ บันทึก หรือแคสต์ Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"เมื่อกำลังแชร์ บันทึก หรือแคสต์แอป Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"เริ่ม"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"ถัดไป"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"การแชร์จะหยุดชั่วคราวเมื่อสลับแอป"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"แชร์แอปนี้แทน"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"เปลี่ยนกลับ"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"การช่วยเหลือพิเศษ"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"แป้นพิมพ์ลัด"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ค้นหาแป้นพิมพ์ลัด"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ไม่พบผลการค้นหา"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ไอคอนยุบ"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ไอคอนขยาย"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"หรือ"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ท่าทางสัมผัสสำหรับหน้าแรก"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ปุ่มดำเนินการ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"เสร็จสิ้น"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"เก่งมาก"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ย้อนกลับ"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาที่ใดก็ได้บนทัชแพด\n\nหรือใช้การดำเนินการแป้นพิมพ์ลัด + ESC ได้เช่นเดียวกัน"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ไปที่หน้าแรก"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ใช้ 3 นิ้วปัดขึ้นจากด้านล่างของหน้าจอเพื่อไปที่หน้าจอหลักได้ทุกเมื่อ"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ทัชแพดแสดงภาพ 3 นิ้วเลื่อนไปทางขวาและซ้าย"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"หน้าจออุปกรณ์แสดงภาพเคลื่อนไหวของท่าทางสัมผัสย้อนกลับ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ระดับที่ %1$d จาก %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ระบบควบคุมอุปกรณ์สมาร์ทโฮม"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"หากต้องการไปที่หน้าแรก ให้ใช้ 3 นิ้วปัดขึ้นบนทัชแพด"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"หากต้องการดูแอปล่าสุด ให้ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"หากต้องการดูแอปทั้งหมด ให้กดปุ่มดำเนินการบนแป้นพิมพ์"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ปกปิดไว้"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ปลดล็อกเพื่อดู"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"ใช้ทัชแพดเพื่อย้อนกลับ"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวา แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ใช้ทัชแพดเพื่อไปยังหน้าแรก"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ใช้แป้นพิมพ์เพื่อดูแอปทั้งหมด"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"กดปุ่มดำเนินการได้ทุกเมื่อ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ตอนนี้การหรี่แสงเพิ่มเติมเป็นส่วนหนึ่งของแถบความสว่างแล้ว"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ตอนนี้คุณสามารถหรี่แสงหน้าจอเพิ่มเติมได้โดยลดระดับความสว่างจากด้านบนของหน้าจอมากขึ้น\n\nฟีเจอร์นี้จะทำงานได้ดีเมื่อคุณอยู่ในที่มืด"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"นำทางลัดหรี่แสงเพิ่มเติมออก"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"นำทางลัดหรี่แสงเพิ่มเติมออกแล้ว หากต้องการลดความสว่าง ให้ใช้แถบความสว่างปกติ"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index f836acacbf25..127fbfa8982a 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Recorder ng Screen"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Simulan ang Pag-record?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Habang nagre-record ka, may access ang Android sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Habang nagre-record ka ng app, may access ang Android sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Simulang mag-record"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Mag-record ng audio"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio ng device"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Tunog mula sa iyong device, gaya ng musika, mga tawag, at ringtone"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Ipadala"</string> <string name="cancel" msgid="1089011503403416730">"Kanselahin"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Logo ng app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Kumpirmahin"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Subukang muli"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"I-tap para kanselahin ang pag-authenticate"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"I-click para magpares ng bagong device"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hindi ma-update ang preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Instant Caption"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Instant Caption"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"I-unblock ang mikropono ng device?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"I-unblock ang camera ng device?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"I-unblock ang camera at mikropono ng device?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mga Setting"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Naka-off"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"I-set up"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Pamahalaan sa mga setting"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Walang aktibong mode}=1{Aktibo ang {mode}}one{# mode ang aktibo}other{# na mode ang aktibo}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban mula sa mga alarm, paalala, event, at tumatawag na tutukuyin mo. Maririnig mo pa rin ang kahit na anong piliin mong i-play kabilang ang mga musika, video, at laro."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Hindi ka maiistorbo ng mga tunog at pag-vibrate, maliban sa mga alarm. Maririnig mo pa rin ang anumang pipiliin mong i-play kabilang ang mga musika, video, at laro."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"I-customize"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mabagal na nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Mga widget sa lock screen"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Naidagdag sa lock screen ang widget na <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"I-customize"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"I-dismiss"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Magkakaroon ng access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Magsimulang mag-record o mag-cast?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ang serbisyong nagbibigay ng function na ito ay magkakaroon ng access sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Buong screen"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Isang app"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"I-share o i-record ang isang app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Simulang mag-record o mag-cast gamit ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kapag nagbabahagi, nagre-record, o nagka-cast ka, may access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kapag nagbabahagi, nagre-record, o nagka-cast ka ng app, may access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Simulan"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ibahagi ang iyong screen sa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Magbahagi ng isang app"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ibahagi ang buong screen"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kapag ibinahagi mo ang iyong buong screen, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong nasa screen mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kapag nagbabahagi ka ng app, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ibahagi ang screen"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Na-disable ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang opsyong ito"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Simulan ang pag-cast?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kapag nagka-cast ka, may access ang Android sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kapag nagka-cast ka ng app, may access ang Android sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Simulan ang pag-cast"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"I-cast ang iyong screen?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Mag-cast ng isang app"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"I-cast ang buong screen"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Kapag na-cast mo ang iyong buong screen, makikita ang anumang nasa screen mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Kapag nagka-cast ka ng app, makikita ang anumang ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"I-cast ang screen"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Simulan ang pagbabahagi?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Kapag nagbabahagi, nagre-record, o nagka-cast ka, may access ang Android sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Kapag nagbabahagi, nagre-record, o nagka-cast ka ng app, may access ang Android sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Simulan"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Susunod"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Magpo-pause ang pagbabahagi kapag lumipat ka ng app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Ibahagi na lang ang app na ito"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Bumalik sa dati"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibility"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Mga keyboard shortcut"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Mga shortcut ng paghahanap"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Walang resulta ng paghahanap"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"I-collapse ang icon"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"I-expand ang icon"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Galaw para sa Home"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tapos na"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Magaling!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Bumalik"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri saanman sa touchpad.\n\nPuwede mo ring gamitin ang keyboard shortcut na Action + ESC para dito."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pumunta sa home"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para pumunta sa iyong home screen anumang oras, mag-swipe pataas gamit ang tatlong daliri mula sa ibaba ng screen. mo."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Touchpad na nagpapakita ng tatlong daliring gumagalaw pakanan at pakaliwa"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Screen ng device na nagpapakita ng animation para sa galaw sa pagbalik"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Backlight ng keyboard"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d sa %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Mga Home Control"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Para pumunta sa home, mag-swipe pataas gamit ang tatlong daliri sa touchpad"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Para tingnan ang kamakailang app, mag-swipe pataas at i-hold gamit ang tatlong daliri sa touchpad"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para tingnan ang lahat ng iyong app, pindutin ang action key sa keyboard mo"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Na-redact"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"I-unlock para tingnan"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Gamitin ang iyong touchpad para bumalik"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Mag-swipe pakaliwa o pakanan gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Gamitin ang touchpad mo para pumunta sa home"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Mag-swipe pataas at i-hold gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gamitin ang iyong keyboard para tingnan ang lahat ng app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pindutin ang action key kahit kailan. I-tap para matuto pa tungkol sa mga galaw."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Bahagi na ng brightness bar ang extra dim"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Puwede mo nang gawing extra dim ang screen sa pamamagitan ng pagpapababa ng level ng liwanag nang higit pa mula sa itaas ng iyong screen.\n\nPinakamahusay itong gumagana kapag nasa madilim na kapaligiran ka."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Alisin ang shortcut ng extra dim"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Inalis ang shortcut ng extra dim. Para bawasan ang liwanag, gamitin ang karaniwang bar ng liwanag."</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index b30df3d0426c..c4a998ff38c6 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekran Kaydedicisi"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Kayıt başlatılsın mı?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Kayıt özelliğini kullandığınızda Android, ekranınızda gösterilen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Bir uygulamayı kaydettiğinizde Android, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Kaydı başlat"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Ses kaydet"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Cihaz sesi"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Müzik, aramalar, zil sesleri gibi cihazınızdan sesler"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Gönder"</string> <string name="cancel" msgid="1089011503403416730">"İptal"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Uygulama logosu"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Onayla"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Tekrar dene"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Kimlik doğrulama işlemini iptal etmek için dokunun"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yeni cihaz eşlemek için tıklayın"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncellenemedi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Hazır Ayar"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Canlı Altyazı"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Canlı Altyazı"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Cihaz mikrofonunun engellemesi kaldırılsın mı?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Cihaz kamerasının engellemesi kaldırılsın mı?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Cihaz kamerası ile mikrofonunun engellemesi kaldırılsın mı?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Kapalı"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Ayarla"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Ayarlarda yönet"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Etkin mod yok}=1{{mode} etkin}other{# mod etkin}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Alarmlar, hatırlatıcılar, etkinlikler ve sizin seçtiğiniz kişilerden gelen çağrılar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Alarmlar dışında hiçbir ses ve titreşimle rahatsız edilmeyeceksiniz. O sırada çaldığınız müzik, seyrettiğiniz video ya da oynadığınız oyunların sesini duymaya devam edeceksiniz."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Özelleştir"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Yavaş şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Kilit ekranındaki widget\'lar"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı kilit ekranına eklendi"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Özelleştir"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Kapat"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Kaydetme veya yayınlama başlatılsın mı?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu işlevi sağlayan hizmet, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Tüm ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Tek bir uygulama"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Uygulamayı paylaşın veya kaydedin"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ile kayıt veya yayınlama başlatılsın mı?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Paylaşma, kaydetme ve yayınlama özelliklerini kullandığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Bir uygulamayı paylaştığınızda, kaydettiğinizde veya yayınladığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Başlat"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekranınız <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> uygulamasıyla paylaşılsın mı?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Tek bir uygulamayı paylaş"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Tüm ekranı paylaş"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, tüm ekranınızı paylaştığınızda ekranınızdaki her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, bir uygulamayı paylaştığınızda o uygulamada gösterilen veya oynatılan her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaş"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu seçeneği devre dışı bıraktı"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Yayın başlatılsın mı?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Yayınlama özelliğini kullandığınızda Android, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Bir uygulamayı yayınladığınızda Android, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Yayını başlat"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Ekranınız yayınlansın mı?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"1 uygulamayı yayınla"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Tüm ekranı yayınla"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Tüm ekranınızı yayınladığınızda ekranınızdaki her şey görünür. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Bir uygulamayı yayınladığınızda o uygulamada gösterilen veya oynatılan her şey görünür. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Ekranı yayınla"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Paylaşma başlatılsın mı?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Paylaşma, kaydetme veya yayınlama özelliğini kullandığınızda Android, ekranınızda gösterilen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Bir uygulamayı paylaştığınızda, kaydettiğinizde veya yayınladığınızda Android, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Başlat"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Sonraki"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Uygulama değiştirdiğinizde paylaşım duraklatılır"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Bunun yerine bu uygulamayı paylaşın"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Geri dön"</string> @@ -612,7 +624,7 @@ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu cihaz ebeveyniniz tarafından yönetiliyor. Kullandığınız uygulamalar, konumunuz ve ekran başında kalma süreniz gibi bilgiler ebeveyniniz tarafından görülüp yönetilebilir."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent tarafından kilit açık tutuldu"</string> - <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Cihaz kilitlendi. Çok fazla sayıda kimlik doğrulama denemesi yapıldı."</string> + <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"Çok fazla kimlik doğrulama denemesi yapıldığından cihaz kilitlendi."</string> <string name="keyguard_indication_after_adaptive_auth_lock" msgid="2323400645470712787">"Cihaz kilitli\nKimlik doğrulama yapılamadı"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="accessibility_volume_settings" msgid="1458961116951564784">"Ses ayarları"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Erişilebilirlik"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klavye kısayolları"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Arama kısayolları"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Arama sonucu yok"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Daralt simgesi"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Genişlet simgesi"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"veya"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ana sayfa hareketi"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Eylem tuşu"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Bitti"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tebrikler!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri dön"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Geri dönmek için dokunmatik alanın herhangi bir yerinde üç parmağınızla sola veya sağa kaydırın.\n\nDilerseniz işlem düğmesi + Esc klavye kısayolunu kullanarak da geri dönebilirsiniz."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ana sayfaya gidin"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"İstediğiniz zaman ana ekrana gitmek için üç parmağınızla ekranınızın altından yukarı doğru kaydırın."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sağa ve sola hareket eden üç parmağın gösterildiği dokunmatik alan"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Geri hareketi animasyonunu gösteren cihaz ekranı"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Seviye %1$d / %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev Kontrolleri"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ana sayfaya gitmek için dokunmatik alanda üç parmağınızla yukarı kaydırın"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Son uygulamaları görüntülemek için dokunmatik alanda üç parmağınızla yukarı kaydırıp basılı tutun"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tüm uygulamalarınızı görüntülemek için klavyenizdeki eylem tuşuna basın"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Çıkartıldı"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Görüntülemek için kilidi açın"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Geri dönmek için dokunmatik alanınızı kullanın"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Üç parmağınızla sola veya sağa kaydırın. Daha fazla hareket öğrenmek için dokunun."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Ana sayfaya gitmek için dokunmatik alanınızı kullanın"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç parmağınızla yukarı kaydırıp basılı tutun. Daha fazla hareket öğrenmek için dokunun."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Tüm uygulamaları görüntülemek için klavyenizi kullanın"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstediğiniz zaman eylem tuşuna basın. Daha fazla hareket öğrenmek için dokunun."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra loş özelliği, parlaklık çubuğuna eklendi"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Artık ekranınızın üst kısmından parlaklık seviyesini daha da düşürerek ekranı ekstra loş hale getirebilirsiniz.\n\nBu özellik, karanlık ortamdayken en iyi sonucu verir."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ekstra loş kısayolunu kaldır"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Ekstra loş kısayolu kaldırıldı. Parlaklık seviyesini düşürmek için normal parlaklık çubuğunu kullanın."</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 7e72f7eb16a5..fd9195a51829 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Запис відео з екрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Почати записування?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Коли ви записуєте вміст екрана, ОС Android отримує доступ до всього, що відображається на ньому або відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Коли ви записуєте додаток, ОС Android отримує доступ до всього, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Почати записування"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Записувати звук"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Звук із пристрою"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Звук із пристрою, зокрема музика, виклики й сигнали дзвінка"</string> @@ -127,13 +137,13 @@ <string name="screenrecord_save_error" msgid="5862648532560118815">"Не вдалося зберегти запис відео з екрана"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"Не вдалося почати запис екрана"</string> <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"Зупинити запис?"</string> - <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Ви зараз записуєте відео з усього екрана"</string> - <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Ви зараз записуєте відео з додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"Ви зараз записуєте вміст усього екрана"</string> + <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"Ви зараз записуєте вміст екрана додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"Зупинити запис"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"Показ екрана"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"Зупинити показ екрана?"</string> - <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Ви зараз ділитеся вмістом усього екрана з додатком <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> - <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Ви зараз ділитеся вмістом усього екрана з додатком"</string> + <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"Ви зараз показуєте вміст усього екрана в додатку <xliff:g id="HOST_APP_NAME">%1$s</xliff:g>"</string> + <string name="share_to_app_stop_dialog_message_entire_screen" msgid="5090115386271179270">"Ви зараз показуєте вміст усього екрана в додатку."</string> <string name="share_to_app_stop_dialog_message_single_app_specific" msgid="5923772039347985172">"Ви зараз показуєте вікно додатка <xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>"</string> <string name="share_to_app_stop_dialog_message_single_app_generic" msgid="6681016774654578261">"Ви зараз показуєте вікно додатка"</string> <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"Зупинити показ"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Надіслати"</string> <string name="cancel" msgid="1089011503403416730">"Скасувати"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Логотип додатка"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Підтвердити"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Повторити спробу"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Натисніть, щоб скасувати автентифікацію"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Натисніть, щоб підключити новий пристрій"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не вдалось оновити набір налаштувань"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набір налаштувань"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Живі субтитри"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Живі субтитри"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Надати доступ до мікрофона?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Надати доступ до камери пристрою?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Надати доступ до камери й мікрофона?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налаштування"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Вимкнено"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Налаштувати"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Керувати в налаштуваннях"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Немає активних режимів}=1{Активовано режим \"{mode}\"}one{Активовано # режим}few{Активовано # режими}many{Активовано # режимів}other{Активовано # режиму}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ви отримуватиме звукові та вібросигнали лише для вибраних будильників, нагадувань, подій і абонентів. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ви отримуватиме звукові та вібросигнали лише для будильників. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Налаштувати"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Повільне заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Віджети на заблокованому екрані"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Віджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" додано на заблокований екран"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Налаштувати"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрити"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"Додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> матиме доступ до всієї інформації, яка з’являється на екрані або відтворюється на пристрої під час запису чи трансляції. Це, зокрема, паролі, платіжна інформація, фотографії, повідомлення і аудіофайли."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Почати запис або трансляцію?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з’являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, платіжної інформації, фотографій, повідомлень і аудіофайлів."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Увесь екран"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Окремий додаток"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Показувати або записувати додаток"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Почати запис або трансляцію за допомогою додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Коли ви показуєте, записуєте або транслюєте екран, додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Коли ви показуєте, записуєте або транслюєте додаток, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається або відтворюється в цьому додатку. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Почати"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показати екран для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показати один додаток"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показати весь екран"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Коли ви показуєте весь екран, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент на ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Коли ви показуєте додаток, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент, що відображається або відтворюється в ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показати екран"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> вимкнув цю опцію"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Почати трансляцію?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Під час трансляції ОС Android отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Коли ви транслюєте додаток, ОС Android отримує доступ до всього, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Почати трансляцію"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Транслювати екран?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Транслювати один додаток"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Транслювати весь екран"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Коли ви транслюєте весь екран, видимим стає весь контент на ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Коли ви транслюєте додаток, видимим стає весь контент, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Транслювати екран"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Почати показ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Коли ви показуєте, записуєте або транслюєте екран, ОС Android отримує доступ до всього, що відображається на ньому чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Коли ви показуєте, записуєте або транслюєте додаток, ОС Android отримує доступ до всього, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Почати"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Далі"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Спільний доступ до додатка призупиняється, коли ви переходите в інший додаток"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Поділитися цим додатком"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Повернутися"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Доступність"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Комбінації клавіш"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Комбінації клавіш для пошуку"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Нічого не знайдено"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок згортання"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок розгортання"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест переходу на головний екран"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дії"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Чудово!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі.\n\nТакож можна скористатися комбінацією \"клавіша дії\" + ESC."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Перейти на головний екран"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Щоб будь-коли перейти на головний екран, проведіть трьома пальцями вгору від нижнього краю екрана."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Сенсорна панель із зображенням трьох пальців, що рухаються вправо й уліво"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Екран пристрою, на якому показано анімацію щодо жесту \"Назад\""</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Підсвічування клавіатури"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Рівень %1$d з %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Автоматизація дому"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Щоб перейти на головний екран, проведіть трьома пальцями вгору по сенсорній панелі"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Щоб переглянути останні додатки, проведіть трьома пальцями вгору по сенсорній панелі й утримуйте їх"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Щоб переглянути всі додатки, натисніть клавішу дії на клавіатурі"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Замасковано"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Розблокуйте, щоб переглянути"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Щоб повернутися, використовуйте сенсорну панель"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Проведіть трьома пальцями вліво чи вправо. Натисніть, щоб дізнатися про інші жести."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Щоб перейти на головний екран, використовуйте сенсорну панель"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Проведіть трьома пальцями вгору й утримуйте їх на екрані. Натисніть, щоб дізнатися про інші жести."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Щоб переглянути всі додатки, використовуйте клавіатуру"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Будь-коли натисніть клавішу дії. Натисніть, щоб дізнатися про інші жести."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Тепер на панелі регулювання яскравості є функція додаткового зменшення яскравості"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Тепер ви можете зробити екран ще темнішим, додатково зменшуючи рівень яскравості вгорі екрана.\n\nНайкраще ця функція працює, коли ви перебуваєте в темному місці."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Видалити комбінацію клавіш для додаткового зменшення яскравості"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Комбінацію клавіш для додаткового зменшення яскравості видалено. Щоб зменшити яскравість, використовуйте стандартну панель регулювання."</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 94586b76c8cb..904399060185 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"اسکرین ریکارڈر"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ریکارڈنگ شروع کریں؟"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"جب آپ ریکارڈنگ کر رہے ہوتے ہیں تو Android کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"جب آپ کسی ایپ کو ریکارڈ کر رہے ہوتے ہیں تو Android کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ریکارڈنگ شروع کریں"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"آڈیو ریکارڈ کریں"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"آلہ کا آڈیو"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"آپ کے آلے سے آواز، جیسے موسیقی، کالز اور رِنگ ٹونز"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"بھیجیں"</string> <string name="cancel" msgid="1089011503403416730">"منسوخ کريں"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"ایپ لوگو"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"تصدیق کریں"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"دوبارہ کوشش کریں"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"تصدیق کو منسوخ کرنے کے لیے تھپتھپائیں"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"نئے آلے کا جوڑا بنانے کے لیے کلک کریں"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"پہلے سے ترتیب شدہ کو اپ ڈیٹ نہیں کیا جا سکا"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"پہلے سے ترتیب شدہ"</string> - <string name="live_caption_title" msgid="8916875614623730005">"لائیو کیپشن"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"لائیو کیپشن"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"آلے کا مائیکروفون غیر مسدود کریں؟"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"آلے کا کیمرا غیر مسدود کریں؟"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"آلے کا کیمرا اور مائیکروفون غیر مسدود کریں؟"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ترتیبات"</string> <string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string> <string name="zen_mode_off" msgid="1736604456618147306">"آف ہے"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"سیٹ اپ کریں"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ترتیبات میں نظم کریں"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{کوئی فعال موڈ نہیں ہے}=1{{mode} فعال ہے}other{# موڈز فعال ہیں}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"الارمز، یاددہانیوں، ایونٹس اور آپ کے متعین کردہ کالرز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ابھی بھی ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"الارمز کے علاوہ، آپ آوازوں اور وائبریشنز سے ڈسٹرب نہیں ہوں گے۔ موسیقی، ویڈیوز اور گیمز سمیت آپ ہر وہ چیز سنیں گے جسے چلانے کا آپ انتخاب کرتے ہیں۔"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"حسب ضرورت بنائیں"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • آہستہ چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"مقفل اسکرین پر ویجیٹس"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"مقفل اسکرین میں <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ شامل کیا گیا"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"حسب ضرورت بنائیں"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"برخاست کریں"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو اس تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر نظر آتی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائی گئی ہے۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات، اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"ریکارڈنگ یا کاسٹنگ شروع کریں؟"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"اس فنکشن فراہم کرنے والی سروس کو اس تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر نظر آتی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائی گئی ہے۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"پوری اسکرین"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"واحد ایپ"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"ایپ کا اشتراک کرنا یا ریکارڈ کرنا"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کا استعمال کر کے ریکارڈنگ یا کاسٹنگ شروع کریں؟"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"جب آپ اشتراک، ریکارڈنگ یا کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"شروع کریں"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کے ساتھ اپنی اسکرین کا اشتراک کریں؟"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ایک ایپ کا اشتراک کریں"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"پوری اسکرین کا اشتراک کریں"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"آپ کے اپنی پوری اسکرین کا اشتراک کرنے پر آپ کی اسکرین پر ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہوجاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"آپ کے کسی ایپ کا اشتراک کرنے پر اس ایپ میں دکھائی گئی یا چلائی گئی ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہو جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"اسکرین کا اشتراک کریں"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> نے اس اختیار کو غیر فعال کر دیا ہے"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"کاسٹ کرنا شروع کریں؟"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"جب آپ کاسٹ کر رہے ہوتے ہیں، تو Android کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"جب آپ کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو Android کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"کاسٹ کرنا شروع کریں"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"اپنی اسکرین کاسٹ کریں؟"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"ایک ایپ کاسٹ کریں"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"پوری اسکرین کاسٹ کریں"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"جب آپ اپنی پوری اسکرین کاسٹ کر رہے ہوتے ہیں تو آپ کی اسکرین پر ہر چیز مرئی ہو جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"جب آپ کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو اس ایپ میں دکھائی گئی یا چلائی گئی ہر چیز مرئی ہو جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"اسکرین کاسٹ کریں"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"اشتراک کرنا شروع کریں؟"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو Android کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"جب آپ اشتراک، ریکارڈنگ یا کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو Android کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"شروع کریں"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"اگلا"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"آپ کے ایپس سوئچ کرنے پر اشتراک موقوف ہو جاتا ہے"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"اس کے بجائے اس ایپ کا اشتراک کریں"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"واپس سوئچ کریں"</string> @@ -679,12 +691,8 @@ <string name="volume_panel_enter_media_output_settings" msgid="8824244246272552669">"آؤٹ پٹ کی ترتیبات درج کریں"</string> <string name="volume_panel_expanded_sliders" msgid="1885750987768506271">"والیوم سلائیڈرز کو پھیلا دیا گیا"</string> <string name="volume_panel_collapsed_sliders" msgid="1413383759434791450">"والیوم سلائیڈرز سکیڑا گیا"</string> - <!-- String.format failed for translation --> - <!-- no translation found for volume_panel_hint_mute (2153922288568199077) --> - <skip /> - <!-- String.format failed for translation --> - <!-- no translation found for volume_panel_hint_unmute (4831850937582282340) --> - <skip /> + <string name="volume_panel_hint_mute" msgid="2153922288568199077">"%s خاموش کریں"</string> + <string name="volume_panel_hint_unmute" msgid="4831850937582282340">"%s غیر خاموش کریں"</string> <string name="volume_panel_hint_muted" msgid="1124844870181285320">"خاموش کردہ"</string> <string name="volume_panel_hint_vibrate" msgid="4136223145435914132">"وائبریٹ"</string> <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> پر چل رہی ہے"</string> @@ -1380,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ایکسیسبیلٹی"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"کی بورڈ شارٹ کٹس"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"تلاش کے شارٹ کٹس"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"تلاش کا کوئی نتیجہ نہیں ہے"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"آئیکن سکیڑیں"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"آئیکن پھیلائیں"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string> @@ -1387,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ہوم کا اشارہ"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ایکشن کلید"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ہو گیا"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"بہترین!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"واپس جائیں"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"واپس جانے کے لیے، ٹچ پیڈ پر کہیں بھی تین انگلیوں کی مدد سے دائیں یا بائیں سوائپ کریں۔\n\nآپ اس کیلئے کی بورڈ شارٹ کٹ ایکشن + Esc کا بھی استعمال کر سکتے ہیں۔"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ہوم پر جائیں"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"کسی بھی وقت اپنی ہوم اسکرین پر جانے کے لیے، تین انگلیوں کی مدد سے اپنی اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں۔"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"ٹچ پیڈ دائیں اور بائیں حرکت کرتی ہوئی تین انگلیاں دکھا رہا ہے"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"آلہ کی اسکرین پیچھے جانے کے اشارے کے لیے اینیمیشن دکھا رہی ہے"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"کی بورڈ بیک لائٹ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d میں سے %1$d کا لیول"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ہوم کنٹرولز"</string> @@ -1404,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"ہوم پر جانے کے لیے، ٹچ پیڈ پر تین انگلیوں کی مدد سے اوپر سوائپ کریں"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"حالیہ ایپس دیکھنے کے لیے، ٹچ پیڈ پر تین انگلیوں سے اوپر سوائپ کریں اور دبائے رکھیں"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"اپنی سبھی ایپس دیکھنے کے لیے، اپنے کی بورڈ پر ایکشن کلید دبائیں"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"چھپانے کیلئے تبدیل کردہ"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"دیکھنے کے لیے غیر مقفل کریں"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"واپس جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"تین انگلیوں سے دائیں یا بائیں طرف سوائپ کریں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"ہوم پر جانے کے لیے اپنے ٹچ پیڈ کا استعمال کریں"</string> @@ -1412,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"تین انگلیوں سے اوپر کی طرف سوائپ کریں اور دبائے رکھیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"سبھی ایپس دیکھنے کے لیے اپنے کی بورڈ کا استعمال کریں"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"کسی بھی وقت ایکشن کلید دبائیں۔ مزید اشارے جاننے کے لیے تھپتھپائیں۔"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"اضافی دھندلا اب چمک بار کا حصہ ہے"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"آپ اپنی اسکرین کے اوپری حصے سے چمکیلے پن لیول کو مزید کم کر کے اپنی اسکرین کو اضافی دھندلی بنا سکتے ہیں۔\n\nجب آپ تاریک ماحول میں ہوتے ہیں تو یہ بہتر کام کرتا ہے۔"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"اضافی دھندلا شارٹ کٹ کو ہٹائیں"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"اضافی دھندلا شارٹ کٹ کو ہٹا دیا گیا۔ اپنا چمکیلا پن کم کرنے کیلئے، ریگولر چمک بار کا استعمال کریں"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 3f6077622404..f58354c87e0b 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Ekranni yozib olish"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Yozib olish boshlansinmi?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Yozib olish vaqtida Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Ilovani yozib olayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Yozib olish"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio yozib olish"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Qurilmadagi audio"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Qurilmangizdagi musiqa, chaqiruvlar va ringtonlar kabi ovozlar"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Yuborish"</string> <string name="cancel" msgid="1089011503403416730">"Bekor qilish"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Ilova logotipi"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"OK"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Qayta urinish"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Tekshiruvni bekor qilish uchun bosing"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yangi qurilmani ulash uchun bosing"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Andoza yangilanmadi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Andoza"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Jonli izoh"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Jonli izoh"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Qurilma kamerasi blokdan chiqarilsinmi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Qurilma kamerasi va mikrofoni blokdan chiqarilsinmi?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Sozlamalar"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Yoqilmagan"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Sozlash"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Sozlamalarda boshqarish"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Hech qanday rejim faol emas}=1{{mode} faol}other{# ta rejim faol}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar, eslatmalar, tadbirlar haqidagi bildirishnomalar va siz tanlagan abonentlardan kelgan chaqiruvlar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Turli ovoz va tebranishlar endi sizni bezovta qilmaydi. Biroq, signallar bundan mustasno. Lekin, ijro etiladigan barcha narsalar, jumladan, musiqa, video va o‘yinlar ovozi eshitiladi."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Sozlash"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Sekin quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Ekran qulfidagi vidjetlar"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Ekran qulfiga <xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidjeti qoʻshildi"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Moslash"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Yopish"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Yozib olish yoki translatsiya boshlansinmi?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyani taʼminlovchi xizmat ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Butun ekran"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Bitta ilova"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Ilovada ulashish yoki yozib olish"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> orqali yozib olish yoki translatsiya boshlansinmi?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Ulashish, yozib olish va translatsiya qilish vaqtida <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Ulashish, yozib olish va translatsiya qilish vaqtida <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Boshlash"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekraningiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bilan ulashilsinmi?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bitta ilovani namoyish qilish"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Butun ekranni namoyish qilish"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Butun ekranni namoyish qilayotganingizda, ekrandagi barcha narsalaringiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Ilovani namoyish qilayotganingizda oʻsha ilova ichida koʻrsatilayotgan yoki ijro qilinayotganlar <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranni namoyish qilish"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu sozlamani faolsizlantirgan"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Translatsiya boshlansinmi?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Translatsiya qilayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Translatsiya qilayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Translatsiyani boshlang"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Ekraningiz uzatilsinmi?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Bitta ilovani uzatish"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Butun ekranni uzatish"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Butun ekran uzatilayotganda, ekrandagi hamma narsa koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Ilovani uzatayotganingizda oʻsha ilova ichida koʻrsatilayotgan yoki ijro qilinayotganlar koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Ekranni translatsiya qilish"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Ulashuv boshlansinmi?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Ulashish, yozib olish va translatsiya qilish vaqtida Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Ilovani ulashish, yozib olish yoki translatsiya qilayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Boshlash"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Keyingisi"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Ilovalarni almashtirsangiz, ulashuv toʻxtatiladi"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Bu ilovani ulashish"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Ortga qaytarish"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Qulayliklar"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tezkor tugmalar"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Tezkor tugmalar qidiruvi"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Hech narsa topilmadi"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Yigʻish belgisi"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Yoyish belgisi"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"yoki"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Asosiy ekran ishorasi"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Amal tugmasi"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tayyor"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Barakalla!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Orqaga qaytish"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Sensorli panelda uchta barmoq chapga va oʻngga harakatlanishi"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Qurilma ekranidagi ortga qaytish ishorasi animatsiyasi"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ortga qaytish uchun sensorli panelda uchta barmoqni chapga yoki oʻngga suring.\n\nBuning uchun Action + ESC tezkor tugmalaridan ham foydalanishingiz mumkin."</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Barakalla!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ortga qaytish ishorasi darsini tamomladingiz."</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Boshiga"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Istalgan vaqtda bosh ekranga oʻtish uchun ekranning pastidan uchta barmoq bilan tepaga suring."</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Yaxshi!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Bosh ekranni ochish ishorasi darsini tamomladingiz."</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"Amal tugmasi"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Ilovalarga kirish uchun klaviaturadagi amal tugmasini bosing"</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Tabriklaymiz!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Amal tugmasi ishorasi darsini tamomladingiz.\n\nAmal + / bosilsa, mavjud buyruqlar koʻrsatiladi."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura orqa yoritkichi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Daraja: %1$d / %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Uy boshqaruvi"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Bosh ekranga qaytish uchun sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Oxirgi ilovalarni koʻrish uchun sensorli panelda uchta barmoq bilan tepaga surib, bosib turing"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Barcha ishoralarni koʻrish uchun klaviaturadagi amal tugmasini bosing"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Chiqarildi"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Koʻrish uchun qulfdan chiqaring"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Sensorli panel orqali orqaga qaytish"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Uchta barmoq bilan chapga yoki oʻngga suring. Boshqa ishoralar bilan tanishish uchun bosing."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Sensorli panel orqali bosh ekranga qaytish"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Uchta barmoq bilan tepaga surib, bosib turing. Boshqa ishoralar bilan tanishish uchun bosing."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatura orqali barcha ilovalarni koʻrish"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Amal tugmasini istalganda bosing. Boshqa ishoralar bilan tanishish uchun bosing."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Juda xira endi yorqinlik panelida joylashgan"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Endi yorqinlik darajasini ekranning yuqori qismidan yanada pasaytirish orqali ekranni yanada xiralashtirishingiz mumkin.\n\nBu qorongʻi muhitda eng yaxshi ishlaydi."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Juda xira yorligʻini olib tashlash"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Juda xira yorligʻi olib tashlandi. Yorqinlikni pasaytirish uchun oddiy yorqinlik panelidan foydalaning."</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index dcf8051d692c..4c4e8aa1a900 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Trình ghi màn hình"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Bắt đầu ghi?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Khi bạn ghi, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Khi bạn ghi một ứng dụng, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Bắt đầu ghi"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Ghi âm"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Âm thanh trên thiết bị"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Âm thanh trên thiết bị, chẳng hạn như nhạc, cuộc gọi và nhạc chuông"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Gửi"</string> <string name="cancel" msgid="1089011503403416730">"Hủy"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Biểu trưng của ứng dụng"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Xác nhận"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Thử lại"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Nhấn để hủy quá trình xác thực"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Nhấp để ghép nối thiết bị mới"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Không cập nhật được giá trị đặt trước"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Chế độ đặt sẵn"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Phụ đề trực tiếp"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Phụ đề trực tiếp"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Bỏ chặn micrô của thiết bị?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Bỏ chặn camera của thiết bị?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Bỏ chặn máy ảnh và micrô của thiết bị?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cài đặt"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Đang tắt"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Thiết lập"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Quản lý trong phần cài đặt"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Không có chế độ nào đang hoạt động}=1{{mode} đang hoạt động}other{# chế độ đang hoạt động}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức, lời nhắc, sự kiện và người gọi mà bạn chỉ định. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Bạn sẽ không bị làm phiền bởi âm thanh và tiếng rung, ngoại trừ báo thức. Bạn sẽ vẫn nghe thấy mọi thứ bạn chọn phát, bao gồm nhạc, video và trò chơi."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Tùy chỉnh"</string> @@ -478,12 +483,11 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc chậm • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Các tiện ích trên màn hình khoá"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Đã thêm tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g> vào màn hình khoá"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tuỳ chỉnh"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Đóng"</string> - <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Thêm, xoá và sắp xếp lại các tiện ích trong không gian này."</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Thêm, xoá và sắp xếp tiện ích trong không gian này."</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Thêm tiện ích khác"</string> <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nhấn và giữ để tuỳ chỉnh tiện ích"</string> <string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Tuỳ chỉnh tiện ích"</string> @@ -507,7 +511,7 @@ <string name="accessibility_action_label_remove_widget" msgid="3373779447448758070">"xoá tiện ích"</string> <string name="accessibility_action_label_place_widget" msgid="1914197458644168978">"đặt tiện ích đã chọn vào vị trí"</string> <string name="communal_widget_picker_title" msgid="1953369090475731663">"Tiện ích trên màn hình khoá"</string> - <string name="communal_widget_picker_description" msgid="490515450110487871">"Ai cũng thấy được các tiện ích trên màn hình khoá, dù bạn đã khoá máy tính bảng."</string> + <string name="communal_widget_picker_description" msgid="490515450110487871">"Ai cũng thấy được tiện ích trên màn hình khoá, kể cả khi khoá máy tính bảng."</string> <string name="accessibility_action_label_unselect_widget" msgid="1041811747619468698">"bỏ chọn tiện ích"</string> <string name="communal_widgets_disclaimer_title" msgid="1150954395585308868">"Tiện ích trên màn hình khoá"</string> <string name="communal_widgets_disclaimer_text" msgid="1423545475160506349">"Để dùng tiện ích mở một ứng dụng, bạn cần xác minh danh tính của mình. Ngoài ra, hãy lưu ý rằng bất kỳ ai cũng có thể xem các tiện ích này, ngay cả khi máy tính bảng của bạn được khoá. Một số tiện ích có thể không dành cho màn hình khoá và không an toàn khi thêm vào đây."</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào tất cả thông tin xuất hiện trên màn hình của bạn hoặc phát trên thiết bị của bạn trong khi ghi âm/ghi hình hoặc truyền, bao gồm cả thông tin như mật khẩu, thông tin thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Bắt đầu ghi hoặc truyền?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Dịch vụ cung cấp chức năng này có quyền truy cập vào tất cả thông tin xuất hiện trên màn hình của bạn hoặc phát trên thiết bị của bạn trong khi ghi hoặc truyền, bao gồm cả thông tin như mật khẩu, thông tin thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Toàn màn hình"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"Một ứng dụng"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Chia sẻ hoặc ghi màn hình ứng dụng"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Bắt đầu ghi hoặc truyền bằng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Khi bạn chia sẻ, ghi hoặc truyền, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Khi bạn chia sẻ, ghi hoặc truyền ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ các thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Bắt đầu"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chia sẻ màn hình của bạn với <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Chia sẻ một ứng dụng"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Chia sẻ toàn bộ màn hình"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Khi bạn chia sẻ toàn bộ màn hình, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung trên màn hình của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Khi bạn chia sẻ một ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung hiển thị hoặc phát trong ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Chia sẻ màn hình"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> đã tắt lựa chọn này"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Bắt đầu truyền?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Khi bạn truyền, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Khi bạn truyền một ứng dụng, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ các thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Bắt đầu truyền"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Truyền màn hình?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Truyền một ứng dụng"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Truyền toàn bộ màn hình"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Khi bạn truyền toàn bộ màn hình thì người khác sẽ thấy được mọi nội dung trên màn hình của bạn. Vì vậy, hãy thận trọng đối với những thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Khi bạn truyền một ứng dụng, thì người khác sẽ thấy được mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng đối với những thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Màn hình truyền"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Bắt đầu chia sẻ?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Khi bạn chia sẻ, ghi hoặc truyền, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Khi bạn chia sẻ, ghi hoặc truyền ứng dụng, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ các thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Bắt đầu"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Tiếp theo"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Quá trình chia sẻ sẽ tạm dừng khi bạn chuyển đổi ứng dụng"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Chia sẻ ứng dụng này"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Chuyển trở lại"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Hỗ trợ tiếp cận"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Phím tắt"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Lối tắt tìm kiếm"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Không có kết quả tìm kiếm nào"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Biểu tượng Thu gọn"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Biểu tượng Mở rộng"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"hoặc"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Cử chỉ chuyển đến màn hình chính"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Phím hành động"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Xong"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Tuyệt vời!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Quay lại"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Để quay lại, hãy dùng 3 ngón tay vuốt sang trái hoặc sang phải ở vị trí bất kỳ trên bàn di chuột.\n\nBạn cũng có thể dùng phím tắt Hành động + ESC cho thao tác này."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Chuyển đến màn hình chính"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Để chuyển đến màn hình chính bất cứ lúc nào, hãy dùng 3 ngón tay vuốt lên từ cuối màn hình lên."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Minh hoạ thao tác di chuyển sang phải và sang trái bằng 3 ngón tay trên bàn di chuột"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Màn hình thiết bị hiện ảnh động minh hoạ cử chỉ quay lại"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Đèn nền bàn phím"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Độ sáng %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Điều khiển nhà"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Để trở về màn hình chính, hãy dùng 3 ngón tay vuốt lên trên bàn di chuột"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Để xem các ứng dụng gần đây, hãy dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Để xem tất cả ứng dụng của bạn, hãy nhấn phím hành động trên bàn phím"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Bị loại bỏ"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Mở khoá để xem"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Dùng bàn di chuột để quay lại"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Dùng 3 ngón tay vuốt sang trái hoặc sang phải. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Dùng bàn di chuột để chuyển đến màn hình chính"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Dùng 3 ngón tay vuốt lên và giữ. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sử dụng bàn phím để xem tất cả ứng dụng"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Nhấn phím hành động bất cứ lúc nào. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Chế độ siêu tối hiện đã có trên thanh độ sáng"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Giờ đây, bạn có thể đặt màn hình ở chế độ siêu tối bằng cách giảm thêm độ sáng từ đầu màn hình.\n\nChế độ này hoạt động hiệu quả nhất khi bạn ở trong một môi trường tối."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Xoá lối tắt của chế độ siêu tối"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Đã xoá lối tắt của chế độ siêu tối. Để giảm độ sáng, hãy dùng thanh độ sáng như thông thường."</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 6162da8304b6..f62ed9077e67 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"屏幕录制器"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"要开始录制吗?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"在录制内容时,Android 可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"在录制某个应用时,Android 可以访问此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"开始录制"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"录制音频"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"设备音频"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"设备发出的声音,例如音乐、通话和铃声"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"发送"</string> <string name="cancel" msgid="1089011503403416730">"取消"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"应用徽标"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"确认"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"重试"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"点按即可取消身份验证"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"点击即可与新设备配对"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"无法更新预设"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"预设"</string> - <string name="live_caption_title" msgid="8916875614623730005">"实时字幕"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"实时字幕"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解锁设备麦克风吗?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解锁设备摄像头吗?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解锁设备摄像头和麦克风吗?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"设置"</string> <string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string> <string name="zen_mode_off" msgid="1736604456618147306">"已关闭"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"设置"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"在设置中管理"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{未启用任何模式}=1{{mode}已启用}other{# 个模式已启用}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"您将不会受到声音和振动的打扰(闹钟、提醒、活动和所指定来电者的相关提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"您将不会受到声音和振动的打扰(闹钟提示音除外)。您依然可以听到您选择播放的任何内容(包括音乐、视频和游戏)的相关音效。"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"自定义"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在慢速充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"锁定屏幕上的微件"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件已添加至锁定屏幕"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自定义"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"关闭"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"在录制或投放内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将可访问屏幕上显示或设备中播放的所有信息,其中包括密码、付款信息、照片、消息及播放的音频等信息。"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"要开始录制或投放内容吗?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在录制或投放内容时,提供此功能的服务将可访问屏幕上显示或设备中播放的所有信息,其中包括密码、付款信息、照片、消息及播放的音频等信息。"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"整个屏幕"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"单个应用"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"分享或录制应用"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"要开始使用<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>录制或投放吗?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"在分享、录制或投放内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"在分享、录制或投放内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>可以访问通过此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"开始"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要与“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”共享屏幕吗?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"共享一个应用"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"共享整个屏幕"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"当您共享整个屏幕时,屏幕上的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"当您共享一个应用时,该应用中显示或播放的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"共享屏幕"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已停用此选项"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"开始投放?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"在投放内容时,Android 可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"在投放某个应用时,Android 可以访问此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"开始投放"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"投放您的屏幕?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"投放单个应用"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"投放整个屏幕"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"投放整个屏幕时,屏幕上的所有内容均公开可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"投放单个应用时,该应用显示或播放的所有内容均公开可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"投放屏幕"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"开始分享?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"在分享内容时,Android 可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"在分享、录制或投放内容时,Android 可以访问通过此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"开始"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"下一步"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"切换应用后,分享会暂停"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"改为分享此应用"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"切换回去"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"无障碍功能"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"键盘快捷键"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"搜索快捷键"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"无搜索结果"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收起图标"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展开图标"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主屏幕手势"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作按键"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"如要返回,请使用三根手指在触控板上的任意位置左滑或右滑。\n\n您也可以使用键盘快捷操作键 + ESC 键进行返回。"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"前往主屏幕"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"若要随时进入主屏幕,请用三根手指从屏幕的底部向上滑动。"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"触控板,其中显示了三根手指右移和左移"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"设备屏幕,其中显示了返回手势的动画"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"键盘背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 级,共 %2$d 级"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"家居控制"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主屏幕,请用三根手指在触控板上向上滑动"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近用过的应用,请用三根手指在触控板上向上滑动并按住"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有应用,请按下键盘上的快捷操作按键"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已隐去"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解锁即可查看"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"使用触控板返回"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"用三根手指向左或向右滑动。点按即可了解更多手势。"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"使用触控板前往主屏幕"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三根手指向上滑动并按住。点按即可了解更多手势。"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用键盘查看所有应用"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"您可随时按下快捷操作按键。点按即可了解更多手势。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"“极暗”功能现已在亮度条中"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"现在,您可从屏幕顶部进一步调低亮度,将屏幕调成极暗。\n\n此功能在昏暗环境中效果最佳。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除“极暗”快捷方式"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"已移除“极暗”快捷方式。如要调低亮度,请使用常规亮度条。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 9c1049b041f6..1be71e835ab3 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影機"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"要開始錄影嗎?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"當你錄影時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"當你錄影應用程式時,Android 可存取在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"開始錄影"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"錄音"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"裝置音訊"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"裝置播放的音效,例如音樂、通話和鈴聲"</string> @@ -139,9 +149,9 @@ <string name="share_to_app_stop_dialog_button" msgid="6334056916284230217">"停止分享"</string> <string name="cast_screen_to_other_device_chip_accessibility_label" msgid="4687917476203009885">"正在投放螢幕"</string> <string name="cast_to_other_device_stop_dialog_title" msgid="7836517190930357326">"要停止投放嗎?"</string> - <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"你正在投放整個螢幕畫面至「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」"</string> + <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device" msgid="1474703115926205251">"你正在將整個螢幕畫面投放到「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」"</string> <string name="cast_to_other_device_stop_dialog_message_entire_screen" msgid="8419219169553867625">"你正在投放整個螢幕畫面至一部附近的裝置"</string> - <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"你正在投放「<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>」至「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」"</string> + <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device" msgid="2715934698604085519">"你正在將「<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>」投放到「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」"</string> <string name="cast_to_other_device_stop_dialog_message_specific_app" msgid="8616103075630934513">"你正在投放「<xliff:g id="APP_BEING_SHARED_NAME">%1$s</xliff:g>」至一部附近的裝置"</string> <string name="cast_to_other_device_stop_dialog_message_generic_with_device" msgid="9213582497852420203">"你正在投放內容至「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」"</string> <string name="cast_to_other_device_stop_dialog_message_generic" msgid="4100272100480415076">"你正在投放內容至一部附近的裝置"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"傳送"</string> <string name="cancel" msgid="1089011503403416730">"取消"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"應用程式標誌"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"請再試一次"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"輕按即可取消驗證"</string> @@ -348,7 +356,7 @@ <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"正在開啟…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"數據節省模式已開啟"</string> <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# 部裝置}other{# 部裝置}}"</string> - <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"電筒"</string> + <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"手電筒"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"相機使用中"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"流動數據"</string> <string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"數據用量"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"㩒一下就可以配對新裝置"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"預設"</string> - <string name="live_caption_title" msgid="8916875614623730005">"即時字幕"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"即時字幕"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"要解除封鎖裝置相機嗎?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要解除封鎖裝置相機和麥克風嗎?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string> <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"在「設定」中管理"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{沒有啟用模式}=1{已啟用{mode}}other{已啟用 # 個模式}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"你不會受到聲音和震動騷擾 (鬧鐘、提醒、活動和你指定的來電者鈴聲除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"你不會受到聲音和震動騷擾 (鬧鐘除外)。當你選擇播放音樂、影片和遊戲等,仍可以聽到該內容的聲音。"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"自訂"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"上鎖畫面上的小工具"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>小工具加咗去上鎖畫面"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"當你錄影或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」將可存取畫面上顯示的任何資料或裝置播放的任何內容,包括密碼、付款資料、相片、訊息和播放的音訊等。"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"要開始錄影或投放嗎?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在錄影或投放時,此功能的服務供應商可存取螢幕顯示或裝置播放的任何資料,當中包括密碼、付款資料、相片、訊息和播放的語音等資料。"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"整個螢幕畫面"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"單一應用程式"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"分享或錄影應用程式"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」錄影或投放嗎?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"當你分享、錄影或投放時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"當你分享、錄影或投放應用程式時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取顯示在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要與「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享螢幕畫面嗎?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享一個應用程式"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個螢幕畫面"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個螢幕畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到你畫面上的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到該應用程式中顯示或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享螢幕畫面"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已停用此選項"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"要開始投放嗎?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"當你投放時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"當你投放應用程式時,Android 可存取在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"開始投放"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"要投放螢幕嗎?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"投放一個應用程式"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"投放整個螢幕畫面"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"當你投放整個螢幕畫面時,其他人可看到你畫面上的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"當你投放應用程式時,其他人可看到該應用程式中顯示或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"投放螢幕畫面"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"要開始分享嗎?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"當你分享、錄影或投放時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"當你分享、錄影或投放應用程式時,Android 可存取顯示在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"開始"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"下一步"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"切換應用程式時,系統會暫停分享"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"改為分享此應用程式"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"切換回先前的應用程式"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"無障礙功能"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"鍵盤快速鍵"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"搜尋快速鍵"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"沒有相符的搜尋結果"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string> @@ -1383,14 +1396,18 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太好了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> - <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> - <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"觸控板上有三隻手指左右移動"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢動畫"</string> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"用三隻手指在觸控板上任何一處向左或向右滑動即可返回。\n\n你也可使用鍵盤快速鍵 Action 鍵 + Esc 鍵執行此操作。"</string> + <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"太好了!"</string> + <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"你已完成「返回」手勢的教學課程。"</string> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"只要用三隻手指從螢幕底部向上滑動,隨時可以返回主畫面。"</string> + <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"做得好!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"你已完成「返回主畫面」手勢的教學課程。"</string> + <string name="tutorial_action_key_title" msgid="2659466586996495447">"快捷操作鍵"</string> + <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"如要存取應用程式,請在鍵盤上按下快捷操作鍵。"</string> + <string name="tutorial_action_key_success_title" msgid="466467860120112933">"恭喜!"</string> + <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"你已完成「快捷操作鍵」手勢的教學課程。\n\n按下動作 + / 鍵即可顯示所有可使用的快速鍵。"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"智能家居"</string> @@ -1400,6 +1417,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要返回主畫面,請用三隻手指在觸控板上向上滑動"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請用三隻手指在觸控板上向上滑動並按住"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請在鍵盤上按下快捷操作鍵"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已剔除"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解鎖即可查看"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"用三隻手指向左或向右滑動。輕按即可瞭解更多手勢。"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板返回主畫面"</string> @@ -1408,4 +1427,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三隻手指向上滑動並按住。輕按即可瞭解更多手勢。"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"隨時按下快捷操作鍵。輕按即可瞭解更多手勢。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"亮度列現已加入超暗功能"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"而家喺螢幕頂部進一步校低亮度,就可以令螢幕變得超暗\n\n呢個功能喺陰暗環境之下嘅效果最好"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除超暗功能快速鍵"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"超暗功能快速鍵已移除。如要降低亮度,請使用一般的亮度列。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 1ac8ec4b69d9..ba0138b50225 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影器"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"要開始錄影嗎?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"你在錄影時,Android 可存取畫面上的所有資訊或裝置播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音等內容。"</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"當你錄製應用程式畫面時,Android 可存取應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音等內容。"</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"開始錄影"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"錄音"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"裝置音訊"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"來自裝置的音訊,例如音樂、通話和鈴聲等等"</string> @@ -126,10 +136,10 @@ <string name="screenrecord_save_text" msgid="3008973099800840163">"輕觸即可查看"</string> <string name="screenrecord_save_error" msgid="5862648532560118815">"儲存螢幕錄影內容時發生錯誤"</string> <string name="screenrecord_start_error" msgid="2200660692479682368">"開始錄製螢幕畫面時發生錯誤"</string> - <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"要停止錄製畫面嗎?"</string> + <string name="screenrecord_stop_dialog_title" msgid="8716193661764511095">"停止錄製?"</string> <string name="screenrecord_stop_dialog_message" msgid="6262768207331626817">"目前正在錄製整個螢幕的畫面"</string> <string name="screenrecord_stop_dialog_message_specific_app" msgid="5995770227684523244">"目前正在錄製「<xliff:g id="APP_NAME">%1$s</xliff:g>」的畫面"</string> - <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"停止錄音"</string> + <string name="screenrecord_stop_dialog_button" msgid="2883812564938194350">"停止錄製"</string> <string name="share_to_app_chip_accessibility_label" msgid="4210256229976947065">"正在分享畫面"</string> <string name="share_to_app_stop_dialog_title" msgid="9212915050910250438">"要停止分享畫面嗎?"</string> <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app" msgid="522823522115375414">"目前正在與「<xliff:g id="HOST_APP_NAME">%1$s</xliff:g>」分享整個畫面"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"傳送"</string> <string name="cancel" msgid="1089011503403416730">"取消"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"應用程式標誌"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"確認"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"再試一次"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"輕觸即可取消驗證"</string> @@ -303,7 +311,7 @@ <string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string> <string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string> <string name="turn_on_bluetooth_auto_tomorrow" msgid="3345758139235739006">"明天自動開啟"</string> - <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"「快速分享」和「尋找我的裝置」等功能都需要使用藍牙技術"</string> + <string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"「快速分享」和「尋找我的裝置」等功能都會使用藍牙技術"</string> <string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"藍牙會在明天早上開啟"</string> <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"分享音訊"</string> <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"正在分享音訊"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"按一下即可配對新裝置"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設設定"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"預設"</string> - <string name="live_caption_title" msgid="8916875614623730005">"即時字幕"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"即時字幕"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"要解除封鎖裝置麥克風嗎?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"解除封鎖裝置相機?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"要將裝置的相機和麥克風解除封鎖嗎?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string> <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"在「設定」中管理"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{未啟用任何模式}=1{已啟用 {mode} 個模式}other{已啟用 # 個模式}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"裝置不會發出音效或震動造成干擾,但是會保留與鬧鐘、提醒、活動和指定來電者有關的設定。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"裝置不會發出音效或震動造成干擾,但是會保留鬧鐘響鈴。如果你選擇播放音樂、影片和遊戲等內容,還是可以聽見相關音訊。"</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"自訂"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 慢速充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"螢幕鎖定畫面上的小工具"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具已新增到螢幕鎖定畫面"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"錄製或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」將可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款資料、相片、訊息和你播放的音訊等資訊。"</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"要開始錄製或投放內容嗎?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"當你錄製或投放內容時,提供這項功能的服務將可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款資料、相片、訊息和你播放的音訊等資訊。"</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"整個螢幕畫面"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"單一應用程式"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"分享或錄製應用程式"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"要開始使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」錄製或投放內容嗎?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"當你分享、錄製或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上顯示的任何資訊或裝置播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"當你分享、錄製或投放應用程式內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取應用程式中顯示的任何資訊或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享畫面嗎?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享單一應用程式的畫面"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個畫面"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取該應用程式顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享畫面"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已停用此選項"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"要開始投放嗎?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"投放時,Android 可存取畫面上顯示的任何資訊或裝置播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音等內容。"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"當你投放應用程式時,Android 可存取應用程式顯示的任何資訊或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音等內容。"</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"開始投放"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"要投放畫面嗎?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"投放一個應用程式"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"投放整個畫面"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"當你投放整個畫面時,畫面上的所有內容都會顯示出來。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"當你投放應用程式畫面時,該應用程式呈現或播放的所有內容都會顯示出來。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"投放螢幕"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"要開始分享嗎?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"當你分享、錄製或投放內容時,Android 將可存取畫面上顯示的任何資訊或裝置播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"當你分享、錄製或投放內容時,Android 可存取應用程式中顯示的任何資訊或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"開始"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"繼續"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"切換應用程式時暫停分享"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"改為分享這個應用程式"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"切回"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"無障礙"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"鍵盤快速鍵"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"搜尋快速鍵"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"找不到相符的搜尋結果"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"太棒了!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"如要返回,請在觸控板的任何位置上用三指向左或向右滑動。\n\n使用快捷操作鍵 + ESC 鍵 (鍵盤快速鍵) 也可以返回。"</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"用 3 指從螢幕底部向上滑動,就能隨時返回主畫面。"</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"動畫顯示三指正在觸控板上向左右移動"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"裝置畫面顯示返回手勢的動畫"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"居家控制"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"如要前往主畫面,請在觸控板上用三指向上滑動"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"如要查看最近使用的應用程式,請在觸控板上向上滑動並按住"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請按下鍵盤上的快捷操作鍵"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已遮蓋"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解鎖即可查看"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"使用觸控板返回"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"用三指向左或向右滑動。輕觸即可進一步瞭解手勢。"</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"使用觸控板前往主畫面"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"用三指向上滑動並按住。輕觸即可進一步瞭解手勢。"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"你隨時可以按下快捷操作鍵。輕觸即可進一步瞭解手勢。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"「超暗」已移到亮度列"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"現在只要在螢幕頂端將亮度設定調得更低,就能讓螢幕變得更暗。\n\n這項設定最適合在昏暗環境下使用。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除「超暗」捷徑"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"「超暗」捷徑已移除。如要調低亮度,請使用一般的亮度列。"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 3a34c47385d7..e28504cc3a8a 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -107,10 +107,20 @@ <string name="screenrecord_title" msgid="4257171601439507792">"Okokuqopha iskrini"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string> - <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Qala Ukurekhoda?"</string> - <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Ngenkathi urekhoda, i-Android inokufinyelela kunoma yini ebonakalayo esikrinini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Ngenkathi urekhoda i-app, i-Android inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"Qala ukurekhoda"</string> + <!-- no translation found for screenrecord_permission_dialog_title (7415261783188749730) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_single_app (1996450687814647583) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (2794896384693120020) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_entire_screen (1321758636709366068) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_warning_single_app (3738199712880063924) --> + <skip /> + <!-- no translation found for screenrecord_permission_dialog_continue_entire_screen (5557974446773486600) --> + <skip /> + <!-- no translation found for screenrecord_app_selector_title (3854492366333954736) --> + <skip /> <string name="screenrecord_audio_label" msgid="6183558856175159629">"Rekhoda umsindo"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Umsindo wedivayisi"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Umsindo ophuma kudivayisi yakho, njengomculo, amakholi, namathoni okukhala"</string> @@ -176,8 +186,6 @@ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"Thumela"</string> <string name="cancel" msgid="1089011503403416730">"Khansela"</string> <string name="biometric_dialog_logo" msgid="7681107853070774595">"Ilogo ye-app"</string> - <string-array name="biometric_dialog_package_names_for_logo_with_overrides"> - </string-array> <string name="biometric_dialog_confirm" msgid="2005978443007344895">"Qinisekisa"</string> <string name="biometric_dialog_try_again" msgid="8575345628117768844">"Zama futhi"</string> <string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"Thepha ukuze ukhansele ukufakazela ubuqiniso"</string> @@ -400,7 +408,7 @@ <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Chofoza ukuze ubhangqe idivayisi entsha"</string> <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ayikwazanga ukubuyekeza ukusetha ngaphambilini"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Ukusetha ngaphambilini"</string> - <string name="live_caption_title" msgid="8916875614623730005">"Amagama-ncazo abukhoma"</string> + <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Amagama-ncazo abukhoma"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vulela imakrofoni yedivayisi?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vulela ikhamera yedivayisi?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vulela ikhamera yedivayisi nemakrofoni?"</string> @@ -434,12 +442,9 @@ <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Amasethingi"</string> <string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Valiwe"</string> - <!-- no translation found for zen_mode_set_up (7457957033034460064) --> - <skip /> - <!-- no translation found for zen_mode_no_manual_invocation (1769975741344633672) --> - <skip /> - <!-- no translation found for zen_mode_active_modes (1625850411578488856) --> - <skip /> + <string name="zen_mode_set_up" msgid="7457957033034460064">"Setha"</string> + <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Phatha kumasethingi"</string> + <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Awekho amamodi asebenzayo}=1{I-{mode} iyasebenza}one{Amamodi angu-# ayasebenza}other{Amamodi angu-# ayasebenza}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ngeke uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu, izikhumbuzi, imicimbi, nabafonayo obacacisayo. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string> <string name="zen_alarms_introduction" msgid="3987266042682300470">"Ngeke uze uphazanyiswe imisindo nokudlidliza, ngaphandle kusukela kuma-alamu. Usazozwa noma yini okhetha ukuyidlala okufaka umculo, amavidiyo, namageyimu."</string> <string name="zen_priority_customize_button" msgid="4119213187257195047">"Enza ngendlela oyifisayo"</string> @@ -478,8 +483,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ishaja kancane • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_action_open_communal_hub" msgid="3081702792413787849">"Amawijethi ekukhiyeni isikrini"</string> - <!-- no translation found for accessibility_announcement_communal_widget_added (6911593106099328271) --> - <skip /> + <string name="accessibility_announcement_communal_widget_added" msgid="6911593106099328271">"Iwijethi ye-<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ifakwe esikrinini sokukhiya"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string> <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Enza ngendlela oyifisayo"</string> <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chitha"</string> @@ -531,22 +535,30 @@ <string name="media_projection_dialog_warning" msgid="1303664408388363598">"I-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> izothola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma idlalwe kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string> <string name="media_projection_sys_service_dialog_title" msgid="3751133258891897878">"Qala ukurekhoda noma ukusakaza?"</string> <string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Isevisi enikezela ngalo msebenzi izothola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma oludlalwa kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string> - <string name="screen_share_permission_dialog_option_entire_screen" msgid="3131200488455089620">"Sonke isikrini"</string> - <string name="screen_share_permission_dialog_option_single_app" msgid="4350961814397220929">"I-app eyodwa"</string> - <string name="screen_share_permission_app_selector_title" msgid="1404878013670347899">"Yabelana noma rekhoda i-app"</string> - <string name="media_projection_entry_app_permission_dialog_title" msgid="9155535851866407199">"Qala ukurekhoda noma ukusakaza nge-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> - <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Uma wabelana, urekhoda, noma usakaza, i-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inokufinyelela kunoma yini ebonakalayo kusikrini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Uma wabelana, ukurekhoda, noma ukusakaza ku-app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezfana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Qala"</string> + <!-- no translation found for screen_share_generic_app_selector_title (8331515850599218288) --> + <skip /> + <string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Yabelana ngesikrini sakho ne-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Yabelana nge-app eyodwa"</string> + <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Yabelana ngesikrini sonke"</string> + <string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Uma wabelana ngesikrini sakho sonke, noma yini esesikrinini sakho ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string> + <string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Uma wabelana nge-app, noma yini eboniswayo noma edlalwayo kuleyo app ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string> + <string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Yabelana ngesikrini"</string> <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ivale le nketho"</string> - <string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Qala ukusakaza?"</string> - <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Uma usakaza, i-Android inokufinyelela kunoma yini ebonakalayo kusikrini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Uma usakaza i-app, i-Android inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string> - <string name="media_projection_entry_cast_permission_dialog_continue" msgid="7209890669948870042">"Qala ukusakaza"</string> + <!-- no translation found for media_projection_entry_share_app_selector_title (1419515119767501822) --> + <skip /> + <string name="media_projection_entry_cast_permission_dialog_title" msgid="752756942658159416">"Sakaza isikrini sakho?"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_single_app" msgid="6073353940838561981">"Sakaza i-app eyodwa"</string> + <string name="media_projection_entry_cast_permission_dialog_option_text_entire_screen" msgid="8389508187954155307">"Sakaza isikrini sonke"</string> + <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="4040447861037324017">"Uma usakaza isikrini sakho sonke, noma yini esesikrinini sakho iyabonakala. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> + <string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="7487834861348460736">"Uma usakaza i-app, noma yini ekhonjiswe noma edlalwe kuleyo-app iyabonakala. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> + <string name="media_projection_entry_cast_permission_dialog_continue_entire_screen" msgid="3261124185304676483">"Isikrini sokusakaza"</string> + <!-- no translation found for media_projection_entry_cast_app_selector_title (6323062146661922387) --> + <skip /> <string name="media_projection_entry_generic_permission_dialog_title" msgid="4519802931547483628">"Qala ukwabelana?"</string> <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen" msgid="5407906851409410209">"Uma wabelana, ukurekhoda, noma ukusakaza, i-Android inokufinyelela kunoma yini ebonakala esikrinini sakho noma okudlalwayo kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> <string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"Uma wabelana, ukurekhoda, noma ukusakaza ku-app, i-Android inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezfana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string> <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"Qala"</string> + <string name="media_projection_entry_generic_permission_dialog_continue_single_app" msgid="5920814988611877051">"Okulandelayo"</string> <string name="media_projection_task_switcher_text" msgid="590885489897412359">"Ukwabelana kuyaphumula uma ushintsha ama-app"</string> <string name="media_projection_task_switcher_action_switch" msgid="8682258717291921123">"Yabelana ngale-app esikhundleni salokho"</string> <string name="media_projection_task_switcher_action_back" msgid="5324164224147845282">"Shintshela emuva"</string> @@ -1376,6 +1388,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Ukufinyeleleka"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Izinqamuleli zekhibhodi"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Sesha izinqamuleli"</string> + <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ayikho imiphumela yosesho"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Goqa isithonjana"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Nweba isithonjana"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"noma"</string> @@ -1383,14 +1396,26 @@ <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ukunyakazisa umzimba kwasekhaya"</string> <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Inkinobho yokufinyelela"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kwenziwe"</string> - <string name="touchpad_tutorial_gesture_done" msgid="4784438360736821255">"Umsebenzi omuhle!"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Buyela emuva"</string> - <!-- no translation found for touchpad_back_gesture_guidance (6263750214998421587) --> + <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu noma yikuphi ephedini yokuthinta.\n\nUngasebenzisa nesinqamuleli sekhibhodi Isenzo + ESC kulokhu."</string> + <!-- no translation found for touchpad_back_gesture_success_title (7240576648330612171) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_body (2324724953720741719) --> + <skip /> + <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Iya ekhasini lokuqala"</string> + <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ukuze uye esikrinini sakho sasekhaya nganoma isiphi isikhathi, swayipha uye phezulu ngeminwe emithathu usuka phansi esikrinini sakho."</string> + <!-- no translation found for touchpad_home_gesture_success_title (3778407003948209795) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2404031094918807067) --> + <skip /> + <!-- no translation found for tutorial_action_key_title (2659466586996495447) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5718948664616999196) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (466467860120112933) --> <skip /> - <!-- no translation found for touchpad_back_gesture_finished (5353616006999726249) --> + <!-- no translation found for tutorial_action_key_success_body (7201991081652850430) --> <skip /> - <string name="touchpad_back_gesture_animation_content_description" msgid="2646107450922379918">"Iphedi yokuthinta ebonisa iminwe emithathu iya kwesokudla nakwesokunxele"</string> - <string name="touchpad_back_gesture_screen_animation_content_description" msgid="4036267494237748710">"Isikrini sedivayisi esibonisa opopayi bokuthinta kwasemuva"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Ilambu lekhibhodi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ileveli %1$d ka-%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Izilawuli Zasekhaya"</string> @@ -1400,6 +1425,8 @@ <string name="home_edu_toast_content" msgid="3381071147871955415">"Ukuze uye ekhaya, swayiphela phezulu ngeminwe emithathu ephedini yokuthinta"</string> <string name="overview_edu_toast_content" msgid="5797030644017804518">"Ukuze ubuke ama-app akamuva, swayiphela phezulu bese ubambe ngeminwe emithathu ephedini yokuthinta"</string> <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ukuze ubuke wonke ama-app wakho, cindezela inkinobho yokufinyelela kukhibhodi yakho"</string> + <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Kwenziwe iredact"</string> + <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Vula ukuze ubuke"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Sebenzisa iphedi yokuthinta ukuze ubuyele emuva"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Sebenzisa iphedi yokuthinta ukuya ekhaya"</string> @@ -1408,4 +1435,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swayiphela phezulu bese uyabamba usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sebenzisa ikhibhodi yakho ukubuka wonke ama-app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Cindezela inkinobho yokufinyelela noma kunini. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ukufiphala okwengeziwe manje sekuyingxenye yebha yokukhanya"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Manje ungenza isikrini sifiphale ngokwengeziwe ngokwehlisa izinga lokukhanya nakakhulu kusukela phezulu kwesikrini sakho.\n\nLokhu kusebenza kahle kakhulu uma usendaweni emnyama."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Susa isinqamuleli esifiphele esengeziwe"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Isinqamuleli esifiphele ngokwengeziwe sikhishiwe. Ukuze wehlise ukukhanya kwakho, sebenzisa ibha yokukhanya evamile."</string> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index f0c8894d7d36..823ff9f54be3 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -1053,4 +1053,15 @@ <!-- List of packages for which we want to use activity info (instead of application info) for biometric prompt logo. Empty for AOSP. [DO NOT TRANSLATE] --> <string-array name="config_useActivityLogoForBiometricPrompt" translatable="false"/> + + <!-- + Whether to enable the desktop specific feature set. + + Refrain from using this from code that needs to make decisions + regarding the size or density of the display. + + Variant owners and OEMs should override this to true when they want to + enable the desktop specific features. + --> + <bool name="config_enableDesktopFeatureSet">false</bool> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f8303ea8e1c6..8a2e767a5a3c 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -756,6 +756,8 @@ <string name="quick_settings_bluetooth_audio_sharing_button">Share audio</string> <!-- QuickSettings: Bluetooth dialog audio sharing button text when sharing audio [CHAR LIMIT=50]--> <string name="quick_settings_bluetooth_audio_sharing_button_sharing">Sharing audio</string> + <!-- QuickSettings: Bluetooth dialog audio sharing button text accessibility label. Used as part of the string "Double tap to enter audio sharing settings". [CHAR LIMIT=50]--> + <string name="quick_settings_bluetooth_audio_sharing_button_accessibility">enter audio sharing settings</string> <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]--> <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java index edf855fe5576..64fe78d9958b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java @@ -19,8 +19,8 @@ package com.android.systemui.shared.recents.model; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; +import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 0da252da5cc9..60fff282d041 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -104,6 +104,7 @@ import android.util.SparseBooleanArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.compose.animation.scene.ObservableTransitionState; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.foldables.FoldGracePeriodProvider; import com.android.internal.jank.InteractionJankMonitor; @@ -119,6 +120,7 @@ import com.android.systemui.CoreStartable; import com.android.systemui.Dumpable; import com.android.systemui.biometrics.AuthController; import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider; +import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; @@ -140,6 +142,9 @@ import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.clocks.WeatherData; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; +import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; +import com.android.systemui.scene.shared.model.Scenes; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; @@ -150,6 +155,7 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostu import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.domain.interactor.SelectedUserInteractor; import com.android.systemui.util.Assert; +import com.android.systemui.util.kotlin.JavaAdapter; import dalvik.annotation.optimization.NeverCompile; @@ -279,6 +285,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final UserTracker mUserTracker; private final KeyguardUpdateMonitorLogger mLogger; private final boolean mIsSystemUser; + private final Provider<JavaAdapter> mJavaAdapter; + private final Provider<SceneInteractor> mSceneInteractor; + private final Provider<AlternateBouncerInteractor> mAlternateBouncerInteractor; private final AuthController mAuthController; private final UiEventLogger mUiEventLogger; private final Set<String> mAllowFingerprintOnOccludingActivitiesFromPackage; @@ -563,7 +572,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ private boolean shouldDismissKeyguardOnTrustGrantedWithCurrentUser(TrustGrantFlags flags) { final boolean isBouncerShowing = - mPrimaryBouncerIsOrWillBeShowing || mAlternateBouncerShowing; + isPrimaryBouncerShowingOrWillBeShowing() || isAlternateBouncerShowing(); return (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) && (mDeviceInteractive || flags.temporaryAndRenewable()) && (isBouncerShowing || flags.dismissKeyguardRequested()); @@ -1170,8 +1179,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Assert.isMainThread(); String reason = mKeyguardBypassController.canBypass() ? "bypass" - : mAlternateBouncerShowing ? "alternateBouncer" - : mPrimaryBouncerFullyShown ? "bouncer" + : isAlternateBouncerShowing() ? "alternateBouncer" + : isPrimaryBouncerFullyShown() ? "bouncer" : "udfpsFpDown"; requestActiveUnlock( ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL, @@ -2169,7 +2178,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider, TaskStackChangeListeners taskStackChangeListeners, SelectedUserInteractor selectedUserInteractor, - IActivityTaskManager activityTaskManagerService) { + IActivityTaskManager activityTaskManagerService, + Provider<AlternateBouncerInteractor> alternateBouncerInteractor, + Provider<JavaAdapter> javaAdapter, + Provider<SceneInteractor> sceneInteractor) { mContext = context; mSubscriptionManager = subscriptionManager; mUserTracker = userTracker; @@ -2214,6 +2226,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFingerprintInteractiveToAuthProvider = interactiveToAuthProvider.orElse(null); mIsSystemUser = mUserManager.isSystemUser(); + mAlternateBouncerInteractor = alternateBouncerInteractor; + mJavaAdapter = javaAdapter; + mSceneInteractor = sceneInteractor; mHandler = new Handler(mainLooper) { @Override @@ -2470,6 +2485,30 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.TIME_12_24), false, mTimeFormatChangeObserver, UserHandle.USER_ALL); + + if (SceneContainerFlag.isEnabled()) { + mJavaAdapter.get().alwaysCollectFlow( + mAlternateBouncerInteractor.get().isVisible(), + this::onAlternateBouncerVisibilityChange); + mJavaAdapter.get().alwaysCollectFlow( + mSceneInteractor.get().getTransitionState(), + this::onTransitionStateChanged + ); + } + } + + @VisibleForTesting + void onAlternateBouncerVisibilityChange(boolean isAlternateBouncerVisible) { + setAlternateBouncerShowing(isAlternateBouncerVisible); + } + + + @VisibleForTesting + void onTransitionStateChanged(ObservableTransitionState transitionState) { + int primaryBouncerFullyShown = isPrimaryBouncerFullyShown(transitionState) ? 1 : 0; + int primaryBouncerIsOrWillBeShowing = + isPrimaryBouncerShowingOrWillBeShowing(transitionState) ? 1 : 0; + handlePrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing, primaryBouncerFullyShown); } private void initializeSimState() { @@ -2717,8 +2756,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab requestActiveUnlock( requestOrigin, extraReason, canFaceBypass - || mAlternateBouncerShowing - || mPrimaryBouncerFullyShown + || isAlternateBouncerShowing() + || isPrimaryBouncerFullyShown() || mAuthController.isUdfpsFingerDown()); } @@ -2739,7 +2778,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void setAlternateBouncerShowing(boolean showing) { mAlternateBouncerShowing = showing; - if (mAlternateBouncerShowing) { + if (isAlternateBouncerShowing()) { requestActiveUnlock( ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT, "alternateBouncer"); @@ -2747,6 +2786,45 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } + private boolean isAlternateBouncerShowing() { + if (SceneContainerFlag.isEnabled()) { + return mAlternateBouncerInteractor.get().isVisibleState(); + } else { + return mAlternateBouncerShowing; + } + } + + private boolean isPrimaryBouncerShowingOrWillBeShowing() { + if (SceneContainerFlag.isEnabled()) { + return isPrimaryBouncerShowingOrWillBeShowing( + mSceneInteractor.get().getTransitionState().getValue()); + } else { + return mPrimaryBouncerIsOrWillBeShowing; + } + } + + private boolean isPrimaryBouncerFullyShown() { + if (SceneContainerFlag.isEnabled()) { + return isPrimaryBouncerFullyShown( + mSceneInteractor.get().getTransitionState().getValue()); + } else { + return mPrimaryBouncerFullyShown; + } + } + + private boolean isPrimaryBouncerShowingOrWillBeShowing( + ObservableTransitionState transitionState + ) { + SceneContainerFlag.assertInNewMode(); + return isPrimaryBouncerFullyShown(transitionState) + || transitionState.isTransitioning(null, Scenes.Bouncer); + } + + private boolean isPrimaryBouncerFullyShown(ObservableTransitionState transitionState) { + SceneContainerFlag.assertInNewMode(); + return transitionState.isIdle(Scenes.Bouncer); + } + /** * If the current state of the device allows for triggering active unlock. This does not * include active unlock availability. @@ -2762,7 +2840,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean shouldTriggerActiveUnlock(boolean shouldLog) { // Triggers: final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant(); - final boolean awakeKeyguard = mPrimaryBouncerFullyShown || mAlternateBouncerShowing + final boolean awakeKeyguard = isPrimaryBouncerFullyShown() || isAlternateBouncerShowing() || (isKeyguardVisible() && !mGoingToSleep && mStatusBarState != StatusBarState.SHADE_LOCKED); @@ -2830,14 +2908,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean shouldListenKeyguardState = isKeyguardVisible() || !mDeviceInteractive - || (mPrimaryBouncerIsOrWillBeShowing && !mKeyguardGoingAway) + || (isPrimaryBouncerShowingOrWillBeShowing() && !mKeyguardGoingAway) || mGoingToSleep || shouldListenForFingerprintAssistant || (mKeyguardOccluded && mIsDreaming) || (mKeyguardOccluded && userDoesNotHaveTrust && mKeyguardShowing && (mOccludingAppRequestingFp || isUdfps - || mAlternateBouncerShowing + || isAlternateBouncerShowing() || mAllowFingerprintOnCurrentOccludingActivity ) ); @@ -2856,7 +2934,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && !isUserInLockdown(user); final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed(); final boolean shouldListenBouncerState = - !strongerAuthRequired || !mPrimaryBouncerIsOrWillBeShowing; + !strongerAuthRequired || !isPrimaryBouncerShowingOrWillBeShowing(); final boolean shouldListenUdfpsState = !isUdfps || (!userCanSkipBouncer @@ -2872,10 +2950,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab user, shouldListen, mAllowFingerprintOnCurrentOccludingActivity, - mAlternateBouncerShowing, + isAlternateBouncerShowing(), biometricEnabledForUser, mBiometricPromptShowing, - mPrimaryBouncerIsOrWillBeShowing, + isPrimaryBouncerShowingOrWillBeShowing(), userCanSkipBouncer, mCredentialAttempted, mDeviceInteractive, @@ -3614,6 +3692,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void sendPrimaryBouncerChanged(boolean primaryBouncerIsOrWillBeShowing, boolean primaryBouncerFullyShown) { + SceneContainerFlag.assertInLegacyMode(); mLogger.logSendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing, primaryBouncerFullyShown); Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED); @@ -4031,10 +4110,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (isUdfpsSupported()) { pw.println(" udfpsEnrolled=" + isUdfpsEnrolled()); pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true)); - pw.println(" mPrimaryBouncerIsOrWillBeShowing=" - + mPrimaryBouncerIsOrWillBeShowing); + pw.println(" isPrimaryBouncerShowingOrWillBeShowing=" + + isPrimaryBouncerShowingOrWillBeShowing()); pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState)); - pw.println(" mAlternateBouncerShowing=" + mAlternateBouncerShowing); + pw.println(" isAlternateBouncerShowing=" + isAlternateBouncerShowing()); } else if (isSfpsSupported()) { pw.println(" sfpsEnrolled=" + isSfpsEnrolled()); pw.println(" shouldListenForSfps=" + shouldListenForFingerprint(false)); diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 63ad41a808dc..13cd2c538f3f 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -53,6 +53,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.res.R; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.shared.animation.PhysicsAnimator; import com.android.wm.shell.shared.animation.PhysicsAnimator.SpringConfig; @@ -63,13 +64,6 @@ import java.util.function.Consumer; public class SwipeHelper implements Gefingerpoken, Dumpable { static final String TAG = "com.android.systemui.SwipeHelper"; private static final boolean DEBUG_INVALIDATE = false; - private static final boolean CONSTRAIN_SWIPE = true; - private static final boolean FADE_OUT_DURING_SWIPE = true; - private static final boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true; - - public static final int X = 0; - public static final int Y = 1; - private static final float SWIPE_ESCAPE_VELOCITY = 500f; // dp/sec private static final int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms private static final int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms @@ -171,10 +165,6 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { mPagingTouchSlop = pagingTouchSlop; } - public void setDisableHardwareLayers(boolean disableHwLayers) { - mDisableHwLayers = disableHwLayers; - } - private float getPos(MotionEvent ev) { return ev.getX(); } @@ -253,13 +243,14 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { float translation) { float swipeProgress = getSwipeProgressForOffset(animView, translation); if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) { - if (FADE_OUT_DURING_SWIPE && dismissable) { - if (!mDisableHwLayers) { - if (swipeProgress != 0f && swipeProgress != 1f) { - animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - } else { - animView.setLayerType(View.LAYER_TYPE_NONE, null); - } + if (dismissable + || (NotificationContentAlphaOptimization.isEnabled() && translation == 0)) { + // We need to reset the content alpha even when the view is not dismissible (eg. + // when Guts is visible) + if (swipeProgress != 0f && swipeProgress != 1f) { + animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } else { + animView.setLayerType(View.LAYER_TYPE_NONE, null); } updateSwipeProgressAlpha(animView, getSwipeAlpha(swipeProgress)); } @@ -436,9 +427,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { duration = fixedDuration; } - if (!mDisableHwLayers) { - animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - } + animView.setLayerType(View.LAYER_TYPE_HARDWARE, null); AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { @@ -493,9 +482,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { if (endAction != null) { endAction.accept(mCancelled); } - if (!mDisableHwLayers) { - animView.setLayerType(View.LAYER_TYPE_NONE, null); - } + animView.setLayerType(View.LAYER_TYPE_NONE, null); onDismissChildWithAnimationFinished(); } }); @@ -612,7 +599,11 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { * view is being animated to dismiss or snap. */ public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) { - updateSwipeProgressFromOffset(animView, canBeDismissed, value); + updateSwipeProgressFromOffset( + animView, + /* dismissable= */ canBeDismissed, + /* translation= */ value + ); } private void snapChildInstantly(final View view) { @@ -689,7 +680,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { } else { // don't let items that can't be dismissed be dragged more than // maxScrollDistance - if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection( + if (!mCallback.canChildBeDismissedInDirection( mTouchedView, delta > 0)) { float size = getSize(mTouchedView); @@ -761,8 +752,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { protected boolean swipedFarEnough() { float translation = getTranslation(mTouchedView); - return DISMISS_IF_SWIPED_FAR_ENOUGH - && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize( + return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize( mTouchedView); } @@ -822,9 +812,18 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { } public void forceResetSwipeState(@NonNull View view) { - if (view.getTranslationX() == 0) return; + if (view.getTranslationX() == 0 + && (!NotificationContentAlphaOptimization.isEnabled() || view.getAlpha() == 1f) + ) { + // Don't do anything when translation is 0 and alpha is 1 + return; + } setTranslation(view, 0); - updateSwipeProgressFromOffset(view, /* dismissable= */ true, 0); + updateSwipeProgressFromOffset( + view, + /* dismissable= */ true, + /* translation= */ 0 + ); } /** This method resets the swipe state, and if `resetAll` is true, also resets the snap state */ @@ -893,7 +892,6 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { pw.append("mTranslation=").println(mTranslation); pw.append("mCanCurrViewBeDimissed=").println(mCanCurrViewBeDimissed); pw.append("mMenuRowIntercepting=").println(mMenuRowIntercepting); - pw.append("mDisableHwLayers=").println(mDisableHwLayers); pw.append("mDismissPendingMap: ").println(mDismissPendingMap.size()); if (!mDismissPendingMap.isEmpty()) { mDismissPendingMap.forEach((view, animator) -> { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java index d81a6862c1c1..6c46318afe47 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java @@ -415,17 +415,13 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks @Override @MainThread public void showMagnificationButton(int displayId, int magnificationMode) { - if (Flags.delayShowMagnificationButton()) { - if (mHandler.hasMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL)) { - return; - } - mHandler.sendMessageDelayed( - mHandler.obtainMessage( - MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL, displayId, magnificationMode), - DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS); - } else { - showMagnificationButtonInternal(displayId, magnificationMode); + if (mHandler.hasMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL)) { + return; } + mHandler.sendMessageDelayed( + mHandler.obtainMessage( + MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL, displayId, magnificationMode), + DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS); } @MainThread @@ -441,9 +437,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks @Override @MainThread public void removeMagnificationButton(int displayId) { - if (Flags.delayShowMagnificationButton()) { - mHandler.removeMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL); - } + mHandler.removeMessages(MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL); mModeSwitchesController.removeButton(displayId); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 3828f9f66857..f0483a5ddaeb 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -112,6 +112,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold MagnificationConstants.SCALE_MAX_VALUE); private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f; + private static final float[] COLOR_BLACK_ARRAY = {0f, 0f, 0f}; private final SparseArray<Float> mMagnificationSizeScaleOptions = new SparseArray<>(); private final Context mContext; @@ -1019,6 +1020,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (!mMirrorSurface.isValid()) { return; } + // Set the surface of the SurfaceView to black to avoid users seeing the contents below the + // magnifier when the mirrored surface has an alpha less than 1. + if (Flags.addBlackBackgroundForWindowMagnifier()) { + mTransaction.setColor(mMirrorSurfaceView.getSurfaceControl(), COLOR_BLACK_ARRAY); + } mTransaction.show(mMirrorSurface) .reparent(mMirrorSurface, mMirrorSurfaceView.getSurfaceControl()); modifyWindowMagnification(false); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java index f4a1f0546135..e4b7b7e69c61 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java @@ -37,6 +37,7 @@ import com.android.systemui.accessibility.AccessibilityButtonModeObserver; import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode; import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.settings.DisplayTracker; import com.android.systemui.util.settings.SecureSettings; @@ -61,6 +62,7 @@ public class AccessibilityFloatingMenuController implements private final SecureSettings mSecureSettings; private final DisplayTracker mDisplayTracker; + private final NavigationModeController mNavigationModeController; @VisibleForTesting IAccessibilityFloatingMenu mFloatingMenu; private int mBtnMode; @@ -106,7 +108,8 @@ public class AccessibilityFloatingMenuController implements AccessibilityButtonModeObserver accessibilityButtonModeObserver, KeyguardUpdateMonitor keyguardUpdateMonitor, SecureSettings secureSettings, - DisplayTracker displayTracker) { + DisplayTracker displayTracker, + NavigationModeController navigationModeController) { mContext = context; mWindowManager = windowManager; mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager; @@ -117,6 +120,7 @@ public class AccessibilityFloatingMenuController implements mKeyguardUpdateMonitor = keyguardUpdateMonitor; mSecureSettings = secureSettings; mDisplayTracker = displayTracker; + mNavigationModeController = navigationModeController; mIsKeyguardVisible = false; } @@ -191,7 +195,8 @@ public class AccessibilityFloatingMenuController implements final Context windowContext = mContext.createWindowContext(defaultDisplay, TYPE_NAVIGATION_BAR_PANEL, /* options= */ null); mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager, - mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings); + mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, + mNavigationModeController); } mFloatingMenu.show(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationController.java index 7fd72ec8ce93..d718ae35dff0 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationController.java @@ -32,7 +32,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Flags; import com.android.wm.shell.common.bubbles.DismissCircleView; import com.android.wm.shell.common.bubbles.DismissView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import java.util.Map; import java.util.Objects; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java index 27ded747fd55..d62162b368fa 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java @@ -77,11 +77,12 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.util.Preconditions; import com.android.systemui.Flags; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.res.R; import com.android.systemui.util.settings.SecureSettings; import com.android.wm.shell.bubbles.DismissViewUtils; import com.android.wm.shell.common.bubbles.DismissView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -142,6 +143,8 @@ class MenuViewLayer extends FrameLayout implements private boolean mIsNotificationShown; private Optional<MenuEduTooltipView> mEduTooltipView = Optional.empty(); private BroadcastReceiver mNotificationActionReceiver; + private NavigationModeController mNavigationModeController; + private NavigationModeController.ModeChangedListener mNavigationModeChangedListender; @IntDef({ LayerIndex.MENU_VIEW, @@ -220,7 +223,8 @@ class MenuViewLayer extends FrameLayout implements MenuViewModel menuViewModel, MenuViewAppearance menuViewAppearance, MenuView menuView, IAccessibilityFloatingMenu floatingMenu, - SecureSettings secureSettings) { + SecureSettings secureSettings, + NavigationModeController navigationModeController) { super(context); // Simplifies the translation positioning and animations @@ -253,6 +257,8 @@ class MenuViewLayer extends FrameLayout implements mNotificationFactory = new MenuNotificationFactory(context); mNotificationManager = context.getSystemService(NotificationManager.class); mStatusBarManager = context.getSystemService(StatusBarManager.class); + mNavigationModeController = navigationModeController; + mNavigationModeChangedListender = (mode -> mMenuView.onPositionChanged()); if (Flags.floatingMenuDragToEdit()) { mDragToInteractAnimationController = new DragToInteractAnimationController( @@ -381,6 +387,7 @@ class MenuViewLayer extends FrameLayout implements mMigrationTooltipObserver); mMessageView.setUndoListener(view -> undo()); getContext().registerComponentCallbacks(this); + mNavigationModeController.addListener(mNavigationModeChangedListender); } @Override @@ -396,6 +403,7 @@ class MenuViewLayer extends FrameLayout implements mMigrationTooltipObserver); mHandler.removeCallbacksAndMessages(/* token= */ null); getContext().unregisterComponentCallbacks(this); + mNavigationModeController.removeListener(mNavigationModeChangedListender); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java index 623536f0f928..cb96e7859fba 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java @@ -24,6 +24,7 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.util.settings.SecureSettings; /** @@ -37,7 +38,8 @@ class MenuViewLayerController implements IAccessibilityFloatingMenu { MenuViewLayerController(Context context, WindowManager windowManager, ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, - AccessibilityManager accessibilityManager, SecureSettings secureSettings) { + AccessibilityManager accessibilityManager, SecureSettings secureSettings, + NavigationModeController navigationModeController) { mWindowManager = viewCaptureAwareWindowManager; MenuViewModel menuViewModel = new MenuViewModel( @@ -49,7 +51,8 @@ class MenuViewLayerController implements IAccessibilityFloatingMenu { menuViewAppearance, new MenuView(context, menuViewModel, menuViewAppearance, secureSettings), this, - secureSettings); + secureSettings, + navigationModeController); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java index a5c5beccefd9..f4e2b82f1773 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java @@ -33,6 +33,7 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import com.android.app.animation.Interpolators; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.systemui.res.R; /** @@ -40,16 +41,17 @@ import com.android.systemui.res.R; */ public class AssistDisclosure { private final Context mContext; - private final WindowManager mWm; + private final ViewCaptureAwareWindowManager mWm; private final Handler mHandler; private AssistDisclosureView mView; private boolean mViewAdded; - public AssistDisclosure(Context context, Handler handler) { + public AssistDisclosure(Context context, Handler handler, + ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) { mContext = context; mHandler = handler; - mWm = mContext.getSystemService(WindowManager.class); + mWm = viewCaptureAwareWindowManager; } public void postShow() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index a67dcdb70b67..939d96e67f8f 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -25,6 +25,7 @@ import android.service.voice.VisualQueryAttentionResult; import android.service.voice.VoiceInteractionSession; import android.util.Log; +import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.app.AssistUtils; import com.android.internal.app.IVisualQueryDetectionAttentionListener; import com.android.internal.app.IVisualQueryRecognitionStatusListener; @@ -195,12 +196,13 @@ public class AssistManager { SecureSettings secureSettings, SelectedUserInteractor selectedUserInteractor, ActivityManager activityManager, - AssistInteractor interactor) { + AssistInteractor interactor, + ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) { mContext = context; mDeviceProvisionedController = controller; mCommandQueue = commandQueue; mAssistUtils = assistUtils; - mAssistDisclosure = new AssistDisclosure(context, uiHandler); + mAssistDisclosure = new AssistDisclosure(context, uiHandler, viewCaptureAwareWindowManager); mOverviewProxyService = overviewProxyService; mPhoneStateMonitor = phoneStateMonitor; mAssistLogger = assistLogger; diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt new file mode 100644 index 000000000000..d69e41626bd6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bluetooth.qsdialog + +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothDevice +import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import java.util.concurrent.Executor +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.merge + +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton +class BluetoothDeviceMetadataInteractor +@Inject +constructor( + deviceItemInteractor: DeviceItemInteractor, + private val bluetoothAdapter: BluetoothAdapter?, + private val logger: BluetoothTileDialogLogger, + @Background private val executor: Executor, + @Background private val backgroundDispatcher: CoroutineDispatcher, +) { + private fun metadataUpdateForDevice(bluetoothDevice: BluetoothDevice): Flow<Unit> = + conflatedCallbackFlow { + val metadataChangedListener = + BluetoothAdapter.OnMetadataChangedListener { device, key, value -> + when (key) { + BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY, + BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY, + BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY, + BluetoothDevice.METADATA_MAIN_BATTERY -> { + trySendWithFailureLogging(Unit, TAG, "onMetadataChanged") + logger.logBatteryChanged(device.address, key, value) + } + } + } + bluetoothAdapter?.addOnMetadataChangedListener( + bluetoothDevice, + executor, + metadataChangedListener + ) + awaitClose { + bluetoothAdapter?.removeOnMetadataChangedListener( + bluetoothDevice, + metadataChangedListener + ) + } + } + + val metadataUpdate: Flow<Unit> = + deviceItemInteractor.deviceItemUpdate + .distinctUntilChangedBy { it.bluetoothDevices } + .flatMapLatest { items -> + items.bluetoothDevices.map { device -> metadataUpdateForDevice(device) }.merge() + } + .flowOn(backgroundDispatcher) + + private companion object { + private const val TAG = "BluetoothDeviceMetadataInteractor" + private val List<DeviceItem>.bluetoothDevices: Set<BluetoothDevice> + get() = + flatMapTo(mutableSetOf()) { item -> + listOf(item.cachedBluetoothDevice.device) + + item.cachedBluetoothDevice.memberDevice.map { it.device } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt index 2808dbe669ab..7deea7335223 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt @@ -129,8 +129,26 @@ internal constructor( getPairNewDeviceButton(dialog).setOnClickListener { bluetoothTileDialogCallback.onPairNewDeviceClicked(it) } - getAudioSharingButtonView(dialog).setOnClickListener { - bluetoothTileDialogCallback.onAudioSharingButtonClicked(it) + getAudioSharingButtonView(dialog).apply { + setOnClickListener { bluetoothTileDialogCallback.onAudioSharingButtonClicked(it) } + accessibilityDelegate = + object : AccessibilityDelegate() { + override fun onInitializeAccessibilityNodeInfo( + host: View, + info: AccessibilityNodeInfo + ) { + super.onInitializeAccessibilityNodeInfo(host, info) + info.addAction( + AccessibilityAction( + AccessibilityAction.ACTION_CLICK.id, + context.getString( + R.string + .quick_settings_bluetooth_audio_sharing_button_accessibility + ) + ) + ) + } + } } getScrollViewContent(dialog).apply { minimumHeight = @@ -445,7 +463,6 @@ internal constructor( internal companion object { const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L - const val MAX_DEVICE_ITEM_ENTRY = 3 const val ACTION_BLUETOOTH_DEVICE_DETAILS = "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS" const val ACTION_PREVIOUSLY_CONNECTED_DEVICE = diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt index 72312b87dc57..06116f0a21c3 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt @@ -90,6 +90,18 @@ constructor(@BluetoothTileDialogLog private val logBuffer: LogBuffer) { { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" } ) + fun logBatteryChanged(address: String, key: Int, value: ByteArray?) = + logBuffer.log( + TAG, + DEBUG, + { + str1 = address + int1 = key + str2 = value?.toString() ?: "" + }, + { "BatteryChanged. address=$str1 key=$int1 value=$str2" } + ) + fun logDeviceFetch(status: JobStatus, trigger: DeviceFetchTrigger, duration: Long) = logBuffer.log( TAG, diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt index 6e51915797cc..56b79d199e09 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt @@ -24,7 +24,7 @@ import javax.inject.Inject /** Repository to get CachedBluetoothDevices for the Bluetooth Dialog. */ @SysUISingleton -internal class BluetoothTileDialogRepository +class BluetoothTileDialogRepository @Inject constructor( private val localBluetoothManager: LocalBluetoothManager?, diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt index 985b1588807b..8b2449aa1ffd 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt @@ -37,7 +37,6 @@ import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Compa import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE -import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -50,8 +49,10 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.produce +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -66,6 +67,7 @@ constructor( private val bluetoothStateInteractor: BluetoothStateInteractor, private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor, private val audioSharingInteractor: AudioSharingInteractor, + private val bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor, private val dialogTransitionAnimator: DialogTransitionAnimator, private val activityStarter: ActivityStarter, private val uiEventLogger: UiEventLogger, @@ -112,15 +114,17 @@ constructor( // deviceItemUpdate is emitted when device item list is done fetching, update UI and // stop the progress bar. - deviceItemInteractor.deviceItemUpdate - .onEach { + combine( + deviceItemInteractor.deviceItemUpdate, + deviceItemInteractor.showSeeAllUpdate + ) { deviceItem, showSeeAll -> updateDialogUiJob?.cancel() updateDialogUiJob = launch { dialogDelegate.apply { onDeviceItemUpdated( dialog, - it.take(MAX_DEVICE_ITEM_ENTRY), - showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY, + deviceItem, + showSeeAll, showPairNewDevice = bluetoothStateInteractor.isBluetoothEnabled() ) @@ -131,8 +135,11 @@ constructor( .launchIn(this) // deviceItemUpdateRequest is emitted when a bluetooth callback is called, re-fetch - // the device item list and animiate the progress bar. - deviceItemInteractor.deviceItemUpdateRequest + // the device item list and animate the progress bar. + merge( + deviceItemInteractor.deviceItemUpdateRequest, + bluetoothDeviceMetadataInteractor.metadataUpdate + ) .onEach { dialogDelegate.animateProgressBar(dialog, true) updateDeviceItemJob?.cancel() diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt index d7893dbb0f90..e846bf7b523c 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt @@ -38,7 +38,7 @@ private val actionAccessibilityLabelDisconnect = R.string.accessibility_quick_settings_bluetooth_device_tap_to_disconnect /** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */ -internal abstract class DeviceItemFactory { +abstract class DeviceItemFactory { abstract fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, @@ -136,7 +136,7 @@ internal class ActiveHearingDeviceItemFactory : ActiveMediaDeviceItemFactory() { } } -internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() { +open class AvailableMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt index 1526cd9675c7..95244964dc44 100644 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt @@ -34,16 +34,18 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext /** Holds business logic for the Bluetooth Dialog after clicking on the Bluetooth QS tile. */ @SysUISingleton -internal class DeviceItemInteractor +class DeviceItemInteractor @Inject constructor( private val bluetoothTileDialogRepository: BluetoothTileDialogRepository, @@ -58,9 +60,13 @@ constructor( private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow(extraBufferCapacity = 1) - internal val deviceItemUpdate + val deviceItemUpdate get() = mutableDeviceItemUpdate.asSharedFlow() + private val mutableShowSeeAllUpdate: MutableStateFlow<Boolean> = MutableStateFlow(false) + internal val showSeeAllUpdate + get() = mutableShowSeeAllUpdate.asStateFlow() + internal val deviceItemUpdateRequest: SharedFlow<Unit> = conflatedCallbackFlow { val listener = @@ -139,7 +145,8 @@ constructor( .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices) // Only emit when the job is not cancelled if (isActive) { - mutableDeviceItemUpdate.tryEmit(deviceItems) + mutableDeviceItemUpdate.tryEmit(deviceItems.take(MAX_DEVICE_ITEM_ENTRY)) + mutableShowSeeAllUpdate.tryEmit(deviceItems.size > MAX_DEVICE_ITEM_ENTRY) logger.logDeviceFetch( JobStatus.FINISHED, trigger, @@ -177,5 +184,6 @@ constructor( companion object { private const val TAG = "DeviceItemInteractor" + private const val MAX_DEVICE_ITEM_ENTRY = 3 } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt index aebc50f92e8d..34107821341d 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt @@ -18,8 +18,6 @@ package com.android.systemui.bouncer.ui import android.app.AlertDialog import android.content.Context -import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModelModule -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModelModule import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.statusbar.phone.SystemUIDialog @@ -27,13 +25,7 @@ import dagger.Binds import dagger.Module import dagger.Provides -@Module( - includes = - [ - BouncerViewModelModule::class, - BouncerMessageViewModelModule::class, - ], -) +@Module interface BouncerViewModule { /** Binds BouncerView to BouncerViewImpl and makes it injectable. */ @Binds fun bindBouncerView(bouncerViewImpl: BouncerViewImpl): BouncerView diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt index 78811a96a026..ad93a25f39a5 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt @@ -9,7 +9,7 @@ import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags import com.android.systemui.bouncer.ui.BouncerDialogFactory -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel @@ -40,7 +40,7 @@ data class ComposeBouncerDependencies @Inject constructor( val legacyInteractor: PrimaryBouncerInteractor, - val viewModel: BouncerViewModel, + val viewModelFactory: BouncerSceneContentViewModel.Factory, val dialogFactory: BouncerDialogFactory, val authenticationInteractor: AuthenticationInteractor, val viewMediatorCallback: ViewMediatorCallback?, @@ -65,7 +65,7 @@ constructor( ComposeBouncerViewBinder.bind( view, deps.legacyInteractor, - deps.viewModel, + deps.viewModelFactory, deps.dialogFactory, deps.authenticationInteractor, deps.selectedUserInteractor, diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt index eaca2767a2e8..c1f7d590d08e 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt @@ -14,7 +14,8 @@ import com.android.systemui.authentication.domain.interactor.AuthenticationInter import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.composable.BouncerContent -import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel +import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.user.domain.interactor.SelectedUserInteractor import kotlinx.coroutines.flow.collectLatest @@ -25,7 +26,7 @@ object ComposeBouncerViewBinder { fun bind( view: ViewGroup, legacyInteractor: PrimaryBouncerInteractor, - viewModel: BouncerViewModel, + viewModelFactory: BouncerSceneContentViewModel.Factory, dialogFactory: BouncerDialogFactory, authenticationInteractor: AuthenticationInteractor, selectedUserInteractor: SelectedUserInteractor, @@ -48,7 +49,14 @@ object ComposeBouncerViewBinder { this@repeatWhenAttached.lifecycle } ) - setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } } + setContent { + PlatformTheme { + BouncerContent( + rememberViewModel { viewModelFactory.create() }, + dialogFactory, + ) + } + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt index 4fbf735a62a2..df50e8fdb90b 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt @@ -17,17 +17,19 @@ package com.android.systemui.bouncer.ui.viewmodel import android.annotation.StringRes +import com.android.app.tracing.coroutines.flow.collectLatest import com.android.systemui.authentication.domain.interactor.AuthenticationResult import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.BouncerInteractor -import kotlinx.coroutines.CoroutineScope +import com.android.systemui.lifecycle.SysUiViewModel +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.receiveAsFlow sealed class AuthMethodBouncerViewModel( - protected val viewModelScope: CoroutineScope, protected val interactor: BouncerInteractor, /** @@ -37,7 +39,7 @@ sealed class AuthMethodBouncerViewModel( * being able to attempt to unlock the device. */ val isInputEnabled: StateFlow<Boolean>, -) { +) : SysUiViewModel() { private val _animateFailure = MutableStateFlow(false) /** @@ -57,6 +59,30 @@ sealed class AuthMethodBouncerViewModel( */ @get:StringRes abstract val lockoutMessageId: Int + private val authenticationRequests = Channel<AuthenticationRequest>(Channel.BUFFERED) + + override suspend fun onActivated(): Nothing { + authenticationRequests.receiveAsFlow().collectLatest { request -> + if (!isInputEnabled.value) { + return@collectLatest + } + + val authenticationResult = + interactor.authenticate( + input = request.input, + tryAutoConfirm = request.useAutoConfirm, + ) + + if (authenticationResult == AuthenticationResult.SKIPPED && request.useAutoConfirm) { + return@collectLatest + } + + _animateFailure.value = authenticationResult != AuthenticationResult.SUCCEEDED + clearInput() + } + awaitCancellation() + } + /** * Notifies that the UI has been hidden from the user (after any transitions have completed). */ @@ -92,14 +118,11 @@ sealed class AuthMethodBouncerViewModel( input: List<Any> = getInput(), useAutoConfirm: Boolean = false, ) { - viewModelScope.launch { - val authenticationResult = interactor.authenticate(input, useAutoConfirm) - if (authenticationResult == AuthenticationResult.SKIPPED && useAutoConfirm) { - return@launch - } - _animateFailure.value = authenticationResult != AuthenticationResult.SUCCEEDED - - clearInput() - } + authenticationRequests.trySend(AuthenticationRequest(input, useAutoConfirm)) } + + private data class AuthenticationRequest( + val input: List<Any>, + val useAutoConfirm: Boolean, + ) } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt index 31479f131ba3..d746220dd7ce 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt @@ -27,7 +27,6 @@ import com.android.systemui.bouncer.shared.model.BouncerMessagePair import com.android.systemui.bouncer.shared.model.BouncerMessageStrings import com.android.systemui.bouncer.shared.model.primaryMessage import com.android.systemui.bouncer.shared.model.secondaryMessage -import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.BiometricMessageInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor @@ -39,19 +38,20 @@ import com.android.systemui.deviceentry.shared.model.FaceLockoutMessage import com.android.systemui.deviceentry.shared.model.FaceTimeoutMessage import com.android.systemui.deviceentry.shared.model.FingerprintFailureMessage import com.android.systemui.deviceentry.shared.model.FingerprintLockoutMessage +import com.android.systemui.lifecycle.SysUiViewModel import com.android.systemui.res.R.string.kg_too_many_failed_attempts_countdown import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel -import com.android.systemui.user.ui.viewmodel.UserViewModel import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.time.SystemClock -import dagger.Module -import dagger.Provides +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import kotlin.math.ceil import kotlin.math.max import kotlin.time.Duration.Companion.seconds -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow @@ -65,20 +65,21 @@ import kotlinx.coroutines.launch /** Holds UI state for the 2-line status message shown on the bouncer. */ @OptIn(ExperimentalCoroutinesApi::class) -class BouncerMessageViewModel( +class BouncerMessageViewModel +@AssistedInject +constructor( @Application private val applicationContext: Context, - @Application private val applicationScope: CoroutineScope, private val bouncerInteractor: BouncerInteractor, private val simBouncerInteractor: SimBouncerInteractor, private val authenticationInteractor: AuthenticationInteractor, - selectedUser: Flow<UserViewModel>, + private val userSwitcherViewModel: UserSwitcherViewModel, private val clock: SystemClock, private val biometricMessageInteractor: BiometricMessageInteractor, private val faceAuthInteractor: DeviceEntryFaceAuthInteractor, private val deviceUnlockedInteractor: DeviceUnlockedInteractor, private val deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor, - flags: ComposeBouncerFlags, -) { + private val flags: ComposeBouncerFlags, +) : SysUiViewModel() { /** * A message shown when the user has attempted the wrong credential too many times and now must * wait a while before attempting to authenticate again. @@ -94,6 +95,26 @@ class BouncerMessageViewModel( /** The user-facing message to show in the bouncer. */ val message: MutableStateFlow<MessageViewModel?> = MutableStateFlow(null) + override suspend fun onActivated(): Nothing { + if (!flags.isComposeBouncerOrSceneContainerEnabled()) { + return awaitCancellation() + } + + coroutineScope { + launch { + // Update the lockout countdown whenever the selected user is switched. + userSwitcherViewModel.selectedUser.collect { startLockoutCountdown() } + } + + launch { defaultBouncerMessageInitializer() } + launch { listenForSimBouncerEvents() } + launch { listenForBouncerEvents() } + launch { listenForFaceMessages() } + launch { listenForFingerprintMessages() } + awaitCancellation() + } + } + /** Initializes the bouncer message to default whenever it is shown. */ fun onShown() { showDefaultMessage() @@ -108,173 +129,161 @@ class BouncerMessageViewModel( private var lockoutCountdownJob: Job? = null - private fun defaultBouncerMessageInitializer() { - applicationScope.launch { - resetToDefault.emit(Unit) - authenticationInteractor.authenticationMethod - .flatMapLatest { authMethod -> - if (authMethod == AuthenticationMethodModel.Sim) { - resetToDefault.map { - MessageViewModel(simBouncerInteractor.getDefaultMessage()) - } - } else if (authMethod.isSecure) { - combine( - deviceUnlockedInteractor.deviceEntryRestrictionReason, - lockoutMessage, - deviceEntryBiometricsAllowedInteractor - .isFingerprintCurrentlyAllowedOnBouncer, - resetToDefault, - ) { deviceEntryRestrictedReason, lockoutMsg, isFpAllowedInBouncer, _ -> - lockoutMsg - ?: deviceEntryRestrictedReason.toMessage( - authMethod, - isFpAllowedInBouncer - ) - } - } else { - emptyFlow() + private suspend fun defaultBouncerMessageInitializer() { + resetToDefault.emit(Unit) + authenticationInteractor.authenticationMethod + .flatMapLatest { authMethod -> + if (authMethod == AuthenticationMethodModel.Sim) { + resetToDefault.map { + MessageViewModel(simBouncerInteractor.getDefaultMessage()) } + } else if (authMethod.isSecure) { + combine( + deviceUnlockedInteractor.deviceEntryRestrictionReason, + lockoutMessage, + deviceEntryBiometricsAllowedInteractor + .isFingerprintCurrentlyAllowedOnBouncer, + resetToDefault, + ) { deviceEntryRestrictedReason, lockoutMsg, isFpAllowedInBouncer, _ -> + lockoutMsg + ?: deviceEntryRestrictedReason.toMessage( + authMethod, + isFpAllowedInBouncer + ) + } + } else { + emptyFlow() } - .collectLatest { messageViewModel -> message.value = messageViewModel } - } + } + .collectLatest { messageViewModel -> message.value = messageViewModel } } - private fun listenForSimBouncerEvents() { + private suspend fun listenForSimBouncerEvents() { // Listen for any events from the SIM bouncer and update the message shown on the bouncer. - applicationScope.launch { - authenticationInteractor.authenticationMethod - .flatMapLatest { authMethod -> - if (authMethod == AuthenticationMethodModel.Sim) { - simBouncerInteractor.bouncerMessageChanged.map { simMsg -> - simMsg?.let { MessageViewModel(it) } - } - } else { - emptyFlow() + authenticationInteractor.authenticationMethod + .flatMapLatest { authMethod -> + if (authMethod == AuthenticationMethodModel.Sim) { + simBouncerInteractor.bouncerMessageChanged.map { simMsg -> + simMsg?.let { MessageViewModel(it) } } + } else { + emptyFlow() } - .collectLatest { - if (it != null) { - message.value = it - } else { - resetToDefault.emit(Unit) - } + } + .collectLatest { + if (it != null) { + message.value = it + } else { + resetToDefault.emit(Unit) } - } + } } - private fun listenForFaceMessages() { + private suspend fun listenForFaceMessages() { // Listen for any events from face authentication and update the message shown on the // bouncer. - applicationScope.launch { - biometricMessageInteractor.faceMessage - .sample( - authenticationInteractor.authenticationMethod, - deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer, - ) - .collectLatest { (faceMessage, authMethod, fingerprintAllowedOnBouncer) -> - val isFaceAuthStrong = faceAuthInteractor.isFaceAuthStrong() - val defaultPrimaryMessage = - BouncerMessageStrings.defaultMessage( - authMethod, - fingerprintAllowedOnBouncer + biometricMessageInteractor.faceMessage + .sample( + authenticationInteractor.authenticationMethod, + deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer, + ) + .collectLatest { (faceMessage, authMethod, fingerprintAllowedOnBouncer) -> + val isFaceAuthStrong = faceAuthInteractor.isFaceAuthStrong() + val defaultPrimaryMessage = + BouncerMessageStrings.defaultMessage(authMethod, fingerprintAllowedOnBouncer) + .primaryMessage + .toResString() + message.value = + when (faceMessage) { + is FaceTimeoutMessage -> + MessageViewModel( + text = defaultPrimaryMessage, + secondaryText = faceMessage.message, + isUpdateAnimated = true ) - .primaryMessage - .toResString() - message.value = - when (faceMessage) { - is FaceTimeoutMessage -> - MessageViewModel( - text = defaultPrimaryMessage, - secondaryText = faceMessage.message, - isUpdateAnimated = true - ) - is FaceLockoutMessage -> - if (isFaceAuthStrong) - BouncerMessageStrings.class3AuthLockedOut(authMethod) - .toMessage() - else - BouncerMessageStrings.faceLockedOut( - authMethod, - fingerprintAllowedOnBouncer - ) - .toMessage() - is FaceFailureMessage -> - BouncerMessageStrings.incorrectFaceInput( + is FaceLockoutMessage -> + if (isFaceAuthStrong) + BouncerMessageStrings.class3AuthLockedOut(authMethod).toMessage() + else + BouncerMessageStrings.faceLockedOut( authMethod, fingerprintAllowedOnBouncer ) .toMessage() - else -> - MessageViewModel( - text = defaultPrimaryMessage, - secondaryText = faceMessage.message, - isUpdateAnimated = false + is FaceFailureMessage -> + BouncerMessageStrings.incorrectFaceInput( + authMethod, + fingerprintAllowedOnBouncer ) - } - delay(MESSAGE_DURATION) - resetToDefault.emit(Unit) - } - } + .toMessage() + else -> + MessageViewModel( + text = defaultPrimaryMessage, + secondaryText = faceMessage.message, + isUpdateAnimated = false + ) + } + delay(MESSAGE_DURATION) + resetToDefault.emit(Unit) + } } - private fun listenForFingerprintMessages() { - applicationScope.launch { - // Listen for any events from fingerprint authentication and update the message shown - // on the bouncer. - biometricMessageInteractor.fingerprintMessage - .sample( - authenticationInteractor.authenticationMethod, - deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer - ) - .collectLatest { (fingerprintMessage, authMethod, isFingerprintAllowed) -> - val defaultPrimaryMessage = - BouncerMessageStrings.defaultMessage(authMethod, isFingerprintAllowed) - .primaryMessage - .toResString() - message.value = - when (fingerprintMessage) { - is FingerprintLockoutMessage -> - BouncerMessageStrings.class3AuthLockedOut(authMethod).toMessage() - is FingerprintFailureMessage -> - BouncerMessageStrings.incorrectFingerprintInput(authMethod) - .toMessage() - else -> - MessageViewModel( - text = defaultPrimaryMessage, - secondaryText = fingerprintMessage.message, - isUpdateAnimated = false - ) - } - delay(MESSAGE_DURATION) - resetToDefault.emit(Unit) - } - } + private suspend fun listenForFingerprintMessages() { + // Listen for any events from fingerprint authentication and update the message shown + // on the bouncer. + biometricMessageInteractor.fingerprintMessage + .sample( + authenticationInteractor.authenticationMethod, + deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer + ) + .collectLatest { (fingerprintMessage, authMethod, isFingerprintAllowed) -> + val defaultPrimaryMessage = + BouncerMessageStrings.defaultMessage(authMethod, isFingerprintAllowed) + .primaryMessage + .toResString() + message.value = + when (fingerprintMessage) { + is FingerprintLockoutMessage -> + BouncerMessageStrings.class3AuthLockedOut(authMethod).toMessage() + is FingerprintFailureMessage -> + BouncerMessageStrings.incorrectFingerprintInput(authMethod).toMessage() + else -> + MessageViewModel( + text = defaultPrimaryMessage, + secondaryText = fingerprintMessage.message, + isUpdateAnimated = false + ) + } + delay(MESSAGE_DURATION) + resetToDefault.emit(Unit) + } } - private fun listenForBouncerEvents() { - // Keeps the lockout message up-to-date. - applicationScope.launch { - bouncerInteractor.onLockoutStarted.collect { startLockoutCountdown() } - } + private suspend fun listenForBouncerEvents() { + coroutineScope { + // Keeps the lockout message up-to-date. + launch { bouncerInteractor.onLockoutStarted.collect { startLockoutCountdown() } } - // Listens to relevant bouncer events - applicationScope.launch { - bouncerInteractor.onIncorrectBouncerInput - .sample( - authenticationInteractor.authenticationMethod, - deviceEntryBiometricsAllowedInteractor.isFingerprintCurrentlyAllowedOnBouncer - ) - .collectLatest { (_, authMethod, isFingerprintAllowed) -> - message.emit( - BouncerMessageStrings.incorrectSecurityInput( - authMethod, - isFingerprintAllowed - ) - .toMessage() + // Listens to relevant bouncer events + launch { + bouncerInteractor.onIncorrectBouncerInput + .sample( + authenticationInteractor.authenticationMethod, + deviceEntryBiometricsAllowedInteractor + .isFingerprintCurrentlyAllowedOnBouncer ) - delay(MESSAGE_DURATION) - resetToDefault.emit(Unit) - } + .collectLatest { (_, authMethod, isFingerprintAllowed) -> + message.emit( + BouncerMessageStrings.incorrectSecurityInput( + authMethod, + isFingerprintAllowed + ) + .toMessage() + ) + delay(MESSAGE_DURATION) + resetToDefault.emit(Unit) + } + } } } @@ -323,10 +332,10 @@ class BouncerMessageViewModel( } /** Shows the countdown message and refreshes it every second. */ - private fun startLockoutCountdown() { + private suspend fun startLockoutCountdown() { lockoutCountdownJob?.cancel() - lockoutCountdownJob = - applicationScope.launch { + lockoutCountdownJob = coroutineScope { + launch { authenticationInteractor.authenticationMethod.collectLatest { authMethod -> do { val remainingSeconds = remainingLockoutSeconds() @@ -352,6 +361,7 @@ class BouncerMessageViewModel( lockoutCountdownJob = null } } + } } private fun remainingLockoutSeconds(): Int { @@ -365,20 +375,9 @@ class BouncerMessageViewModel( private fun Int.toResString(): String = applicationContext.getString(this) - init { - if (flags.isComposeBouncerOrSceneContainerEnabled()) { - applicationScope.launch { - // Update the lockout countdown whenever the selected user is switched. - selectedUser.collect { startLockoutCountdown() } - } - - defaultBouncerMessageInitializer() - - listenForSimBouncerEvents() - listenForBouncerEvents() - listenForFaceMessages() - listenForFingerprintMessages() - } + @AssistedFactory + interface Factory { + fun create(): BouncerMessageViewModel } companion object { @@ -398,40 +397,3 @@ data class MessageViewModel( */ val isUpdateAnimated: Boolean = true, ) - -@OptIn(ExperimentalCoroutinesApi::class) -@Module -object BouncerMessageViewModelModule { - - @Provides - @SysUISingleton - fun viewModel( - @Application applicationContext: Context, - @Application applicationScope: CoroutineScope, - bouncerInteractor: BouncerInteractor, - simBouncerInteractor: SimBouncerInteractor, - authenticationInteractor: AuthenticationInteractor, - clock: SystemClock, - biometricMessageInteractor: BiometricMessageInteractor, - faceAuthInteractor: DeviceEntryFaceAuthInteractor, - deviceUnlockedInteractor: DeviceUnlockedInteractor, - deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor, - flags: ComposeBouncerFlags, - userSwitcherViewModel: UserSwitcherViewModel, - ): BouncerMessageViewModel { - return BouncerMessageViewModel( - applicationContext = applicationContext, - applicationScope = applicationScope, - bouncerInteractor = bouncerInteractor, - simBouncerInteractor = simBouncerInteractor, - authenticationInteractor = authenticationInteractor, - clock = clock, - biometricMessageInteractor = biometricMessageInteractor, - faceAuthInteractor = faceAuthInteractor, - deviceUnlockedInteractor = deviceUnlockedInteractor, - deviceEntryBiometricsAllowedInteractor = deviceEntryBiometricsAllowedInteractor, - flags = flags, - selectedUser = userSwitcherViewModel.selectedUser, - ) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt new file mode 100644 index 000000000000..2a272714db37 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bouncer.ui.viewmodel + +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.bouncer.domain.interactor.BouncerInteractor +import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.map + +/** + * Models UI state for user actions that can lead to navigation to other scenes when showing the + * bouncer scene. + */ +class BouncerSceneActionsViewModel +@AssistedInject +constructor( + private val bouncerInteractor: BouncerInteractor, +) : SceneActionsViewModel() { + + override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) { + bouncerInteractor.dismissDestination + .map { prevScene -> + mapOf( + Back to UserActionResult(prevScene), + Swipe(SwipeDirection.Down) to UserActionResult(prevScene), + ) + } + .collectLatest { actions -> setActions(actions) } + } + + @AssistedFactory + interface Factory { + fun create(): BouncerSceneActionsViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt index e2089bbb4504..63b6f0193502 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt @@ -23,125 +23,63 @@ import android.graphics.Bitmap import androidx.compose.ui.input.key.KeyEvent import androidx.compose.ui.input.key.type import androidx.core.graphics.drawable.toBitmap -import com.android.compose.animation.scene.Back -import com.android.compose.animation.scene.Swipe -import com.android.compose.animation.scene.SwipeDirection -import com.android.compose.animation.scene.UserAction -import com.android.compose.animation.scene.UserActionResult import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationWipeModel import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor import com.android.systemui.bouncer.domain.interactor.BouncerInteractor -import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text -import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.inputmethod.domain.interactor.InputMethodInteractor -import com.android.systemui.user.domain.interactor.SelectedUserInteractor -import com.android.systemui.user.ui.viewmodel.UserActionViewModel +import com.android.systemui.lifecycle.SysUiViewModel import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel -import com.android.systemui.user.ui.viewmodel.UserViewModel -import dagger.Module -import dagger.Provides -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.Flow +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.job import kotlinx.coroutines.launch -/** Holds UI state and handles user input on bouncer UIs. */ -class BouncerViewModel( +/** Models UI state for the content of the bouncer scene. */ +class BouncerSceneContentViewModel +@AssistedInject +constructor( @Application private val applicationContext: Context, - @Deprecated("TODO(b/354270224): remove this. Injecting CoroutineScope to view-models is banned") - @Application - private val applicationScope: CoroutineScope, - @Main private val mainDispatcher: CoroutineDispatcher, private val bouncerInteractor: BouncerInteractor, - private val inputMethodInteractor: InputMethodInteractor, - private val simBouncerInteractor: SimBouncerInteractor, private val authenticationInteractor: AuthenticationInteractor, - private val selectedUserInteractor: SelectedUserInteractor, private val devicePolicyManager: DevicePolicyManager, - bouncerMessageViewModel: BouncerMessageViewModel, - flags: ComposeBouncerFlags, - selectedUser: Flow<UserViewModel>, - users: Flow<List<UserViewModel>>, - userSwitcherMenu: Flow<List<UserActionViewModel>>, - actionButton: Flow<BouncerActionButtonModel?>, -) { - val selectedUserImage: StateFlow<Bitmap?> = - selectedUser - .map { it.image.toBitmap() } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = null, - ) - - val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - bouncerInteractor.dismissDestination.map { prevScene -> - mapOf( - Back to UserActionResult(prevScene), - Swipe(SwipeDirection.Down) to UserActionResult(prevScene), - ) - } - - val message: BouncerMessageViewModel = bouncerMessageViewModel - + private val bouncerMessageViewModelFactory: BouncerMessageViewModel.Factory, + private val flags: ComposeBouncerFlags, + private val userSwitcher: UserSwitcherViewModel, + private val actionButtonInteractor: BouncerActionButtonInteractor, + private val pinViewModelFactory: PinBouncerViewModel.Factory, + private val patternViewModelFactory: PatternBouncerViewModel.Factory, + private val passwordViewModelFactory: PasswordBouncerViewModel.Factory, +) : SysUiViewModel() { + private val _selectedUserImage = MutableStateFlow<Bitmap?>(null) + val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow() + + val message: BouncerMessageViewModel by lazy { bouncerMessageViewModelFactory.create() } + + private val _userSwitcherDropdown = + MutableStateFlow<List<UserSwitcherDropdownItemViewModel>>(emptyList()) val userSwitcherDropdown: StateFlow<List<UserSwitcherDropdownItemViewModel>> = - combine( - users, - userSwitcherMenu, - ) { users, actions -> - users.map { user -> - UserSwitcherDropdownItemViewModel( - icon = Icon.Loaded(user.image, contentDescription = null), - text = user.name, - onClick = user.onClicked ?: {}, - ) - } + - actions.map { action -> - UserSwitcherDropdownItemViewModel( - icon = Icon.Resource(action.iconResourceId, contentDescription = null), - text = Text.Resource(action.textResourceId), - onClick = action.onClicked, - ) - } - } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = emptyList(), - ) + _userSwitcherDropdown.asStateFlow() val isUserSwitcherVisible: Boolean get() = bouncerInteractor.isUserSwitcherVisible - // Handle to the scope of the child ViewModel (stored in [authMethod]). - private var childViewModelScope: CoroutineScope? = null - /** View-model for the current UI, based on the current authentication method. */ + private val _authMethodViewModel = MutableStateFlow<AuthMethodBouncerViewModel?>(null) val authMethodViewModel: StateFlow<AuthMethodBouncerViewModel?> = - authenticationInteractor.authenticationMethod - .map(::getChildViewModel) - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = null, - ) + _authMethodViewModel.asStateFlow() /** * A message for a dialog to show when the user has attempted the wrong credential too many @@ -160,31 +98,24 @@ class BouncerViewModel( */ private val wipeDialogMessage = MutableStateFlow<String?>(null) + private val _dialogViewModel = MutableStateFlow<DialogViewModel?>(createDialogViewModel()) /** * Models the dialog to be shown to the user, or `null` if no dialog should be shown. * * Once the dialog is shown, the UI should call [DialogViewModel.onDismiss] when the user * dismisses this dialog. */ - val dialogViewModel: StateFlow<DialogViewModel?> = - combine(wipeDialogMessage, lockoutDialogMessage) { _, _ -> createDialogViewModel() } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = createDialogViewModel(), - ) + val dialogViewModel: StateFlow<DialogViewModel?> = _dialogViewModel.asStateFlow() + private val _actionButton = MutableStateFlow<BouncerActionButtonModel?>(null) /** * The bouncer action button (Return to Call / Emergency Call). If `null`, the button should not * be shown. */ - val actionButton: StateFlow<BouncerActionButtonModel?> = - actionButton.stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = null - ) + val actionButton: StateFlow<BouncerActionButtonModel?> = _actionButton.asStateFlow() + private val _isSideBySideSupported = + MutableStateFlow(isSideBySideSupported(authMethodViewModel.value)) /** * Whether the "side-by-side" layout is supported. * @@ -193,45 +124,99 @@ class BouncerViewModel( * side-by-side layout; these need to be shown with the standard layout so they can take up as * much width as possible. */ - val isSideBySideSupported: StateFlow<Boolean> = - authMethodViewModel - .map { authMethod -> isSideBySideSupported(authMethod) } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = isSideBySideSupported(authMethodViewModel.value), - ) + val isSideBySideSupported: StateFlow<Boolean> = _isSideBySideSupported.asStateFlow() + private val _isFoldSplitRequired = + MutableStateFlow(isFoldSplitRequired(authMethodViewModel.value)) /** * Whether the splitting the UI around the fold seam (where the hinge is on a foldable device) * is required. */ - val isFoldSplitRequired: StateFlow<Boolean> = - authMethodViewModel - .map { authMethod -> isFoldSplitRequired(authMethod) } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = isFoldSplitRequired(authMethodViewModel.value), - ) - - private val isInputEnabled: StateFlow<Boolean> = - bouncerMessageViewModel.isLockoutMessagePresent - .map { lockoutMessagePresent -> !lockoutMessagePresent } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = authenticationInteractor.lockoutEndTimestamp == null, - ) + val isFoldSplitRequired: StateFlow<Boolean> = _isFoldSplitRequired.asStateFlow() + + private val _isInputEnabled = + MutableStateFlow(authenticationInteractor.lockoutEndTimestamp == null) + private val isInputEnabled: StateFlow<Boolean> = _isInputEnabled.asStateFlow() + + override suspend fun onActivated(): Nothing { + coroutineScope { + launch { message.activate() } + launch { + authenticationInteractor.authenticationMethod + .map(::getChildViewModel) + .collectLatest { childViewModelOrNull -> + _authMethodViewModel.value = childViewModelOrNull + childViewModelOrNull?.activate() + } + } - init { - if (flags.isComposeBouncerOrSceneContainerEnabled()) { - // Keeps the upcoming wipe dialog up-to-date. - applicationScope.launch { + launch { authenticationInteractor.upcomingWipe.collect { wipeModel -> wipeDialogMessage.value = wipeModel?.message } } + + launch { + userSwitcher.selectedUser + .map { it.image.toBitmap() } + .collectLatest { _selectedUserImage.value = it } + } + + launch { + combine( + userSwitcher.users, + userSwitcher.menu, + ) { users, actions -> + users.map { user -> + UserSwitcherDropdownItemViewModel( + icon = Icon.Loaded(user.image, contentDescription = null), + text = user.name, + onClick = user.onClicked ?: {}, + ) + } + + actions.map { action -> + UserSwitcherDropdownItemViewModel( + icon = + Icon.Resource( + action.iconResourceId, + contentDescription = null + ), + text = Text.Resource(action.textResourceId), + onClick = action.onClicked, + ) + } + } + .collectLatest { _userSwitcherDropdown.value = it } + } + + launch { + combine(wipeDialogMessage, lockoutDialogMessage) { _, _ -> createDialogViewModel() } + .collectLatest { _dialogViewModel.value = it } + } + + launch { + actionButtonInteractor.actionButton.collectLatest { _actionButton.value = it } + } + + launch { + authMethodViewModel + .map { authMethod -> isSideBySideSupported(authMethod) } + .collectLatest { _isSideBySideSupported.value = it } + } + + launch { + authMethodViewModel + .map { authMethod -> isFoldSplitRequired(authMethod) } + .collectLatest { _isFoldSplitRequired.value = it } + } + + launch { + message.isLockoutMessagePresent + .map { lockoutMessagePresent -> !lockoutMessagePresent } + .collectLatest { _isInputEnabled.value = it } + } + + awaitCancellation() } } @@ -253,46 +238,28 @@ class BouncerViewModel( return childViewModel } - childViewModelScope?.cancel() - val newViewModelScope = createChildCoroutineScope(applicationScope) - childViewModelScope = newViewModelScope return when (authenticationMethod) { is AuthenticationMethodModel.Pin -> - PinBouncerViewModel( - applicationContext = applicationContext, - viewModelScope = newViewModelScope, - interactor = bouncerInteractor, - isInputEnabled = isInputEnabled, - simBouncerInteractor = simBouncerInteractor, + pinViewModelFactory.create( authenticationMethod = authenticationMethod, - onIntentionalUserInput = ::onIntentionalUserInput + onIntentionalUserInput = ::onIntentionalUserInput, + isInputEnabled = isInputEnabled, ) is AuthenticationMethodModel.Sim -> - PinBouncerViewModel( - applicationContext = applicationContext, - viewModelScope = newViewModelScope, - interactor = bouncerInteractor, - isInputEnabled = isInputEnabled, - simBouncerInteractor = simBouncerInteractor, + pinViewModelFactory.create( authenticationMethod = authenticationMethod, - onIntentionalUserInput = ::onIntentionalUserInput + onIntentionalUserInput = ::onIntentionalUserInput, + isInputEnabled = isInputEnabled, ) is AuthenticationMethodModel.Password -> - PasswordBouncerViewModel( - viewModelScope = newViewModelScope, + passwordViewModelFactory.create( + onIntentionalUserInput = ::onIntentionalUserInput, isInputEnabled = isInputEnabled, - interactor = bouncerInteractor, - inputMethodInteractor = inputMethodInteractor, - selectedUserInteractor = selectedUserInteractor, - onIntentionalUserInput = ::onIntentionalUserInput ) is AuthenticationMethodModel.Pattern -> - PatternBouncerViewModel( - applicationContext = applicationContext, - viewModelScope = newViewModelScope, - interactor = bouncerInteractor, + patternViewModelFactory.create( + onIntentionalUserInput = ::onIntentionalUserInput, isInputEnabled = isInputEnabled, - onIntentionalUserInput = ::onIntentionalUserInput ) else -> null } @@ -303,12 +270,6 @@ class BouncerViewModel( bouncerInteractor.onIntentionalUserInput() } - private fun createChildCoroutineScope(parentScope: CoroutineScope): CoroutineScope { - return CoroutineScope( - SupervisorJob(parent = parentScope.coroutineContext.job) + mainDispatcher - ) - } - /** * @return A message warning the user that the user/profile/device will be wiped upon a further * [AuthenticationWipeModel.remainingAttempts] unsuccessful authentication attempts. @@ -396,44 +357,9 @@ class BouncerViewModel( val text: Text, val onClick: () -> Unit, ) -} -@Module -object BouncerViewModelModule { - - @Provides - @SysUISingleton - fun viewModel( - @Application applicationContext: Context, - @Application applicationScope: CoroutineScope, - @Main mainDispatcher: CoroutineDispatcher, - bouncerInteractor: BouncerInteractor, - imeInteractor: InputMethodInteractor, - simBouncerInteractor: SimBouncerInteractor, - actionButtonInteractor: BouncerActionButtonInteractor, - authenticationInteractor: AuthenticationInteractor, - selectedUserInteractor: SelectedUserInteractor, - flags: ComposeBouncerFlags, - userSwitcherViewModel: UserSwitcherViewModel, - devicePolicyManager: DevicePolicyManager, - bouncerMessageViewModel: BouncerMessageViewModel, - ): BouncerViewModel { - return BouncerViewModel( - applicationContext = applicationContext, - applicationScope = applicationScope, - mainDispatcher = mainDispatcher, - bouncerInteractor = bouncerInteractor, - inputMethodInteractor = imeInteractor, - simBouncerInteractor = simBouncerInteractor, - authenticationInteractor = authenticationInteractor, - selectedUserInteractor = selectedUserInteractor, - devicePolicyManager = devicePolicyManager, - bouncerMessageViewModel = bouncerMessageViewModel, - flags = flags, - selectedUser = userSwitcherViewModel.selectedUser, - users = userSwitcherViewModel.users, - userSwitcherMenu = userSwitcherViewModel.menu, - actionButton = actionButtonInteractor.actionButton, - ) + @AssistedFactory + interface Factory { + fun create(): BouncerSceneContentViewModel } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt index 052fb6b3c4d7..c91fd6a1a18e 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt @@ -23,29 +23,34 @@ import com.android.systemui.inputmethod.domain.interactor.InputMethodInteractor import com.android.systemui.res.R import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.kotlin.onSubscriberAdded +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import kotlin.time.Duration.Companion.milliseconds -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch /** Holds UI state and handles user input for the password bouncer UI. */ -class PasswordBouncerViewModel( - viewModelScope: CoroutineScope, - isInputEnabled: StateFlow<Boolean>, +class PasswordBouncerViewModel +@AssistedInject +constructor( interactor: BouncerInteractor, - private val onIntentionalUserInput: () -> Unit, private val inputMethodInteractor: InputMethodInteractor, private val selectedUserInteractor: SelectedUserInteractor, + @Assisted isInputEnabled: StateFlow<Boolean>, + @Assisted private val onIntentionalUserInput: () -> Unit, ) : AuthMethodBouncerViewModel( - viewModelScope = viewModelScope, interactor = interactor, isInputEnabled = isInputEnabled, ) { @@ -59,28 +64,71 @@ class PasswordBouncerViewModel( override val lockoutMessageId = R.string.kg_too_many_failed_password_attempts_dialog_message + private val _isImeSwitcherButtonVisible = MutableStateFlow(false) /** Informs the UI whether the input method switcher button should be visible. */ - val isImeSwitcherButtonVisible: StateFlow<Boolean> = imeSwitcherRefreshingFlow() + val isImeSwitcherButtonVisible: StateFlow<Boolean> = _isImeSwitcherButtonVisible.asStateFlow() /** Whether the text field element currently has focus. */ private val isTextFieldFocused = MutableStateFlow(false) + private val _isTextFieldFocusRequested = + MutableStateFlow(isInputEnabled.value && !isTextFieldFocused.value) /** Whether the UI should request focus on the text field element. */ - val isTextFieldFocusRequested = - combine(isInputEnabled, isTextFieldFocused) { hasInput, hasFocus -> hasInput && !hasFocus } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(), - initialValue = isInputEnabled.value && !isTextFieldFocused.value, - ) + val isTextFieldFocusRequested = _isTextFieldFocusRequested.asStateFlow() + private val _selectedUserId = MutableStateFlow(selectedUserInteractor.getSelectedUserId()) /** The ID of the currently-selected user. */ - val selectedUserId: StateFlow<Int> = - selectedUserInteractor.selectedUser.stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(), - initialValue = selectedUserInteractor.getSelectedUserId(), - ) + val selectedUserId: StateFlow<Int> = _selectedUserId.asStateFlow() + + private val requests = Channel<Request>(Channel.BUFFERED) + + override suspend fun onActivated(): Nothing { + coroutineScope { + launch { super.onActivated() } + launch { + requests.receiveAsFlow().collect { request -> + when (request) { + is OnImeSwitcherButtonClicked -> { + inputMethodInteractor.showInputMethodPicker( + displayId = request.displayId, + showAuxiliarySubtypes = false, + ) + } + is OnImeDismissed -> { + interactor.onImeHiddenByUser() + } + } + } + } + launch { + combine(isInputEnabled, isTextFieldFocused) { hasInput, hasFocus -> + hasInput && !hasFocus + } + .collectLatest { _isTextFieldFocusRequested.value = it } + } + launch { + selectedUserInteractor.selectedUser.collectLatest { _selectedUserId.value = it } + } + launch { + // Re-fetch the currently-enabled IMEs whenever the selected user changes, and + // whenever + // the UI subscribes to the `isImeSwitcherButtonVisible` flow. + combine( + // InputMethodManagerService sometimes takes some time to update its + // internal + // state when the selected user changes. As a workaround, delay fetching the + // IME + // info. + selectedUserInteractor.selectedUser.onEach { delay(DELAY_TO_FETCH_IMES) }, + _isImeSwitcherButtonVisible.onSubscriberAdded() + ) { selectedUserId, _ -> + inputMethodInteractor.hasMultipleEnabledImesOrSubtypes(selectedUserId) + } + .collectLatest { _isImeSwitcherButtonVisible.value = it } + } + awaitCancellation() + } + } override fun onHidden() { super.onHidden() @@ -106,9 +154,7 @@ class PasswordBouncerViewModel( /** Notifies that the user clicked the button to change the input method. */ fun onImeSwitcherButtonClicked(displayId: Int) { - viewModelScope.launch { - inputMethodInteractor.showInputMethodPicker(displayId, showAuxiliarySubtypes = false) - } + requests.trySend(OnImeSwitcherButtonClicked(displayId)) } /** Notifies that the user has pressed the key for attempting to authenticate the password. */ @@ -120,7 +166,7 @@ class PasswordBouncerViewModel( /** Notifies that the user has dismissed the software keyboard (IME). */ fun onImeDismissed() { - viewModelScope.launch { interactor.onImeHiddenByUser() } + requests.trySend(OnImeDismissed) } /** Notifies that the password text field has gained or lost focus. */ @@ -128,34 +174,21 @@ class PasswordBouncerViewModel( isTextFieldFocused.value = isFocused } - /** - * Whether the input method switcher button should be displayed in the password bouncer UI. The - * value may be stale at the moment of subscription to this flow, but it is guaranteed to be - * shortly updated with a fresh value. - * - * Note: Each added subscription triggers an IPC call in the background, so this should only be - * subscribed to by the UI once in its lifecycle (i.e. when the bouncer is shown). - */ - private fun imeSwitcherRefreshingFlow(): StateFlow<Boolean> { - val isImeSwitcherButtonVisible = MutableStateFlow(value = false) - viewModelScope.launch { - // Re-fetch the currently-enabled IMEs whenever the selected user changes, and whenever - // the UI subscribes to the `isImeSwitcherButtonVisible` flow. - combine( - // InputMethodManagerService sometimes takes some time to update its internal - // state when the selected user changes. As a workaround, delay fetching the IME - // info. - selectedUserInteractor.selectedUser.onEach { delay(DELAY_TO_FETCH_IMES) }, - isImeSwitcherButtonVisible.onSubscriberAdded() - ) { selectedUserId, _ -> - inputMethodInteractor.hasMultipleEnabledImesOrSubtypes(selectedUserId) - } - .collect { isImeSwitcherButtonVisible.value = it } - } - return isImeSwitcherButtonVisible.asStateFlow() + @AssistedFactory + interface Factory { + fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + ): PasswordBouncerViewModel } companion object { @VisibleForTesting val DELAY_TO_FETCH_IMES = 300.milliseconds } + + private sealed interface Request + + private data class OnImeSwitcherButtonClicked(val displayId: Int) : Request + + private data object OnImeDismissed : Request } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt index 8b9c0a9a0bdd..4c029299e16b 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt @@ -22,28 +22,33 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.res.R +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import kotlin.math.max import kotlin.math.min import kotlin.math.pow import kotlin.math.sqrt -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch /** Holds UI state and handles user input for the pattern bouncer UI. */ -class PatternBouncerViewModel( +class PatternBouncerViewModel +@AssistedInject +constructor( private val applicationContext: Context, - viewModelScope: CoroutineScope, interactor: BouncerInteractor, - isInputEnabled: StateFlow<Boolean>, - private val onIntentionalUserInput: () -> Unit, + @Assisted isInputEnabled: StateFlow<Boolean>, + @Assisted private val onIntentionalUserInput: () -> Unit, ) : AuthMethodBouncerViewModel( - viewModelScope = viewModelScope, interactor = interactor, isInputEnabled = isInputEnabled, ) { @@ -54,17 +59,10 @@ class PatternBouncerViewModel( /** The number of rows in the dot grid. */ val rowCount = 3 - private val _selectedDots = MutableStateFlow<LinkedHashSet<PatternDotViewModel>>(linkedSetOf()) - + private val selectedDotSet = MutableStateFlow<LinkedHashSet<PatternDotViewModel>>(linkedSetOf()) + private val selectedDotList = MutableStateFlow(selectedDotSet.value.toList()) /** The dots that were selected by the user, in the order of selection. */ - val selectedDots: StateFlow<List<PatternDotViewModel>> = - _selectedDots - .map { it.toList() } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(), - initialValue = emptyList(), - ) + val selectedDots: StateFlow<List<PatternDotViewModel>> = selectedDotList.asStateFlow() private val _currentDot = MutableStateFlow<PatternDotViewModel?>(null) @@ -83,6 +81,18 @@ class PatternBouncerViewModel( override val lockoutMessageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message + override suspend fun onActivated(): Nothing { + coroutineScope { + launch { super.onActivated() } + launch { + selectedDotSet + .map { it.toList() } + .collectLatest { selectedDotList.value = it.toList() } + } + awaitCancellation() + } + } + /** Notifies that the user has started a drag gesture across the dot grid. */ fun onDragStart() { onIntentionalUserInput() @@ -120,7 +130,7 @@ class PatternBouncerViewModel( } val hitDot = dots.value.firstOrNull { dot -> dot.x == dotColumn && dot.y == dotRow } - if (hitDot != null && !_selectedDots.value.contains(hitDot)) { + if (hitDot != null && !selectedDotSet.value.contains(hitDot)) { val skippedOverDots = currentDot.value?.let { previousDot -> buildList { @@ -147,9 +157,9 @@ class PatternBouncerViewModel( } } ?: emptyList() - _selectedDots.value = + selectedDotSet.value = linkedSetOf<PatternDotViewModel>().apply { - addAll(_selectedDots.value) + addAll(selectedDotSet.value) addAll(skippedOverDots) add(hitDot) } @@ -172,11 +182,11 @@ class PatternBouncerViewModel( override fun clearInput() { _dots.value = defaultDots() _currentDot.value = null - _selectedDots.value = linkedSetOf() + selectedDotSet.value = linkedSetOf() } override fun getInput(): List<Any> { - return _selectedDots.value.map(PatternDotViewModel::toCoordinate) + return selectedDotSet.value.map(PatternDotViewModel::toCoordinate) } private fun defaultDots(): List<PatternDotViewModel> { @@ -204,6 +214,14 @@ class PatternBouncerViewModel( max(min(outValue.float, 1f), MIN_DOT_HIT_FACTOR) } + @AssistedFactory + interface Factory { + fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + ): PatternBouncerViewModel + } + companion object { private const val MIN_DOT_HIT_FACTOR = 0.2f } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt index aa447ffac154..c6119544d2b0 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt @@ -32,29 +32,35 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor import com.android.systemui.res.R -import kotlinx.coroutines.CoroutineScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch /** Holds UI state and handles user input for the PIN code bouncer UI. */ -class PinBouncerViewModel( +class PinBouncerViewModel +@AssistedInject +constructor( applicationContext: Context, - viewModelScope: CoroutineScope, interactor: BouncerInteractor, - isInputEnabled: StateFlow<Boolean>, - private val onIntentionalUserInput: () -> Unit, private val simBouncerInteractor: SimBouncerInteractor, - authenticationMethod: AuthenticationMethodModel, + @Assisted isInputEnabled: StateFlow<Boolean>, + @Assisted private val onIntentionalUserInput: () -> Unit, + @Assisted override val authenticationMethod: AuthenticationMethodModel, ) : AuthMethodBouncerViewModel( - viewModelScope = viewModelScope, interactor = interactor, isInputEnabled = isInputEnabled, ) { @@ -73,69 +79,90 @@ class PinBouncerViewModel( /** Currently entered pin keys. */ val pinInput: StateFlow<PinInputViewModel> = mutablePinInput + private val _hintedPinLength = MutableStateFlow<Int?>(null) /** The length of the PIN for which we should show a hint. */ - val hintedPinLength: StateFlow<Int?> = - if (isSimAreaVisible) { - flowOf(null) - } else { - interactor.hintedPinLength - } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + val hintedPinLength: StateFlow<Int?> = _hintedPinLength.asStateFlow() + private val _backspaceButtonAppearance = MutableStateFlow(ActionButtonAppearance.Hidden) /** Appearance of the backspace button. */ val backspaceButtonAppearance: StateFlow<ActionButtonAppearance> = - combine( - mutablePinInput, - interactor.isAutoConfirmEnabled, - ) { mutablePinEntries, isAutoConfirmEnabled -> - computeBackspaceButtonAppearance( - pinInput = mutablePinEntries, - isAutoConfirmEnabled = isAutoConfirmEnabled, - ) - } - .stateIn( - scope = viewModelScope, - // Make sure this is kept as WhileSubscribed or we can run into a bug where the - // downstream continues to receive old/stale/cached values. - started = SharingStarted.WhileSubscribed(), - initialValue = ActionButtonAppearance.Hidden, - ) + _backspaceButtonAppearance.asStateFlow() + private val _confirmButtonAppearance = MutableStateFlow(ActionButtonAppearance.Hidden) /** Appearance of the confirm button. */ val confirmButtonAppearance: StateFlow<ActionButtonAppearance> = - interactor.isAutoConfirmEnabled - .map { if (it) ActionButtonAppearance.Hidden else ActionButtonAppearance.Shown } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(), - initialValue = ActionButtonAppearance.Hidden, - ) - - override val authenticationMethod: AuthenticationMethodModel = authenticationMethod + _confirmButtonAppearance.asStateFlow() override val lockoutMessageId = R.string.kg_too_many_failed_pin_attempts_dialog_message - init { - viewModelScope.launch { simBouncerInteractor.subId.collect { onResetSimFlow() } } + private val requests = Channel<Request>(Channel.BUFFERED) + + override suspend fun onActivated(): Nothing { + coroutineScope { + launch { super.onActivated() } + launch { + requests.receiveAsFlow().collect { request -> + when (request) { + is OnErrorDialogDismissed -> { + simBouncerInteractor.onErrorDialogDismissed() + } + is OnAuthenticateButtonClickedForSim -> { + isSimUnlockingDialogVisible.value = true + simBouncerInteractor.verifySim(getInput()) + isSimUnlockingDialogVisible.value = false + clearInput() + } + } + } + } + launch { simBouncerInteractor.subId.collect { onResetSimFlow() } } + launch { + if (isSimAreaVisible) { + flowOf(null) + } else { + interactor.hintedPinLength + } + .collectLatest { _hintedPinLength.value = it } + } + launch { + combine( + mutablePinInput, + interactor.isAutoConfirmEnabled, + ) { mutablePinEntries, isAutoConfirmEnabled -> + computeBackspaceButtonAppearance( + pinInput = mutablePinEntries, + isAutoConfirmEnabled = isAutoConfirmEnabled, + ) + } + .collectLatest { _backspaceButtonAppearance.value = it } + } + launch { + interactor.isAutoConfirmEnabled + .map { if (it) ActionButtonAppearance.Hidden else ActionButtonAppearance.Shown } + .collectLatest { _confirmButtonAppearance.value = it } + } + launch { + interactor.isPinEnhancedPrivacyEnabled + .map { !it } + .collectLatest { _isDigitButtonAnimationEnabled.value = it } + } + awaitCancellation() + } } /** Notifies that the user dismissed the sim pin error dialog. */ fun onErrorDialogDismissed() { - viewModelScope.launch { simBouncerInteractor.onErrorDialogDismissed() } + requests.trySend(OnErrorDialogDismissed) } + private val _isDigitButtonAnimationEnabled = + MutableStateFlow(!interactor.isPinEnhancedPrivacyEnabled.value) /** * Whether the digit buttons should be animated when touched. Note that this doesn't affect the * delete or enter buttons; those should always animate. */ val isDigitButtonAnimationEnabled: StateFlow<Boolean> = - interactor.isPinEnhancedPrivacyEnabled - .map { !it } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(), - initialValue = !interactor.isPinEnhancedPrivacyEnabled.value, - ) + _isDigitButtonAnimationEnabled.asStateFlow() /** Notifies that the user clicked on a PIN button with the given digit value. */ fun onPinButtonClicked(input: Int) { @@ -163,19 +190,14 @@ class PinBouncerViewModel( /** Notifies that the user clicked the "enter" button. */ fun onAuthenticateButtonClicked() { if (authenticationMethod == AuthenticationMethodModel.Sim) { - viewModelScope.launch { - isSimUnlockingDialogVisible.value = true - simBouncerInteractor.verifySim(getInput()) - isSimUnlockingDialogVisible.value = false - clearInput() - } + requests.trySend(OnAuthenticateButtonClickedForSim) } else { tryAuthenticate(useAutoConfirm = false) } } fun onDisableEsimButtonClicked() { - viewModelScope.launch { simBouncerInteractor.disableEsim() } + simBouncerInteractor.disableEsim() } /** Resets the sim screen and shows a default message. */ @@ -242,6 +264,21 @@ class PinBouncerViewModel( else -> false } } + + @AssistedFactory + interface Factory { + fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + authenticationMethod: AuthenticationMethodModel, + ): PinBouncerViewModel + } + + private sealed interface Request + + private data object OnErrorDialogDismissed : Request + + private data object OnAuthenticateButtonClickedForSim : Request } /** Appearance of pin-pad action buttons. */ diff --git a/packages/SystemUI/src/com/android/systemui/common/usagestats/data/CommonUsageStatsDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/CommonUsageStatsDataLayerModule.kt new file mode 100644 index 000000000000..3faa0ddf8099 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/CommonUsageStatsDataLayerModule.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data + +import com.android.systemui.common.usagestats.data.repository.UsageStatsRepository +import com.android.systemui.common.usagestats.data.repository.UsageStatsRepositoryImpl +import dagger.Binds +import dagger.Module + +@Module +abstract class CommonUsageStatsDataLayerModule { + @Binds + abstract fun bindUsageStatsRepository(impl: UsageStatsRepositoryImpl): UsageStatsRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/common/usagestats/data/model/UsageStatsQuery.kt b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/model/UsageStatsQuery.kt new file mode 100644 index 000000000000..270498c5323e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/model/UsageStatsQuery.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data.model + +import android.annotation.CurrentTimeMillisLong +import android.app.usage.UsageStatsManager +import android.os.UserHandle +import com.android.systemui.util.time.SystemClock + +/** Models a query which can be made to [UsageStatsManager] */ +data class UsageStatsQuery( + /** Specifies the user for the query. */ + val user: UserHandle, + /** + * The inclusive beginning of the range of events to include. Defined in unix time, see + * [SystemClock.currentTimeMillis] + */ + @CurrentTimeMillisLong val startTime: Long, + /** + * The exclusive end of the range of events to include. Defined in unix time, see + * [SystemClock.currentTimeMillis] + */ + @CurrentTimeMillisLong val endTime: Long, + /** + * The list of package names to be included in the query. If empty, events for all packages will + * be queried. + */ + val packageNames: List<String> = emptyList(), +) diff --git a/packages/SystemUI/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepository.kt b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepository.kt new file mode 100644 index 000000000000..e3f1174d4a5f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepository.kt @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data.repository + +import android.app.usage.UsageEvents +import android.app.usage.UsageEventsQuery +import android.app.usage.UsageStatsManager +import com.android.app.tracing.coroutines.withContext +import com.android.systemui.common.usagestats.data.model.UsageStatsQuery +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel.Lifecycle +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext + +/** Repository for querying UsageStatsManager */ +interface UsageStatsRepository { + /** Query activity events. */ + suspend fun queryActivityEvents(query: UsageStatsQuery): List<ActivityEventModel> +} + +@SysUISingleton +class UsageStatsRepositoryImpl +@Inject +constructor( + @Background private val bgContext: CoroutineContext, + private val usageStatsManager: UsageStatsManager, +) : UsageStatsRepository { + private companion object { + const val TAG = "UsageStatsRepository" + } + + override suspend fun queryActivityEvents(query: UsageStatsQuery): List<ActivityEventModel> = + withContext("$TAG#queryActivityEvents", bgContext) { + val systemQuery: UsageEventsQuery = + UsageEventsQuery.Builder(query.startTime, query.endTime) + .apply { + setUserId(query.user.identifier) + setEventTypes( + UsageEvents.Event.ACTIVITY_RESUMED, + UsageEvents.Event.ACTIVITY_PAUSED, + UsageEvents.Event.ACTIVITY_STOPPED, + UsageEvents.Event.ACTIVITY_DESTROYED, + ) + if (query.packageNames.isNotEmpty()) { + setPackageNames(*query.packageNames.toTypedArray()) + } + } + .build() + + val events: UsageEvents? = usageStatsManager.queryEvents(systemQuery) + + buildList { + events.forEachEvent { event -> + val lifecycle = + when (event.eventType) { + UsageEvents.Event.ACTIVITY_RESUMED -> Lifecycle.RESUMED + UsageEvents.Event.ACTIVITY_PAUSED -> Lifecycle.PAUSED + UsageEvents.Event.ACTIVITY_STOPPED -> Lifecycle.STOPPED + UsageEvents.Event.ACTIVITY_DESTROYED -> Lifecycle.DESTROYED + else -> Lifecycle.UNKNOWN + } + + add( + ActivityEventModel( + instanceId = event.instanceId, + packageName = event.packageName, + lifecycle = lifecycle, + timestamp = event.timeStamp, + ) + ) + } + } + } +} + +private inline fun UsageEvents?.forEachEvent(action: (UsageEvents.Event) -> Unit) { + this ?: return + val event = UsageEvents.Event() + while (getNextEvent(event)) { + action(event) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/common/usagestats/domain/UsageStatsInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/usagestats/domain/UsageStatsInteractor.kt new file mode 100644 index 000000000000..81848e294c30 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/usagestats/domain/UsageStatsInteractor.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.domain + +import android.annotation.CurrentTimeMillisLong +import android.os.UserHandle +import com.android.systemui.common.usagestats.data.model.UsageStatsQuery +import com.android.systemui.common.usagestats.data.repository.UsageStatsRepository +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.settings.UserTracker +import com.android.systemui.util.time.SystemClock +import javax.inject.Inject + +@SysUISingleton +class UsageStatsInteractor +@Inject +constructor( + private val userTracker: UserTracker, + private val repository: UsageStatsRepository, + private val systemClock: SystemClock, +) { + suspend fun queryActivityEvents( + @CurrentTimeMillisLong startTime: Long, + @CurrentTimeMillisLong endTime: Long = systemClock.currentTimeMillis(), + userHandle: UserHandle = UserHandle.CURRENT, + packageNames: List<String> = emptyList(), + ): List<ActivityEventModel> { + val user = + if (userHandle == UserHandle.CURRENT) { + userTracker.userHandle + } else { + userHandle + } + + return repository.queryActivityEvents( + UsageStatsQuery( + startTime = startTime, + endTime = endTime, + user = user, + packageNames = packageNames, + ) + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/common/usagestats/shared/model/ActivityEventModel.kt b/packages/SystemUI/src/com/android/systemui/common/usagestats/shared/model/ActivityEventModel.kt new file mode 100644 index 000000000000..9ef33fa25833 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/usagestats/shared/model/ActivityEventModel.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.shared.model + +import android.annotation.CurrentTimeMillisLong +import android.app.Activity +import com.android.systemui.util.time.SystemClock + +/** Represents [Activity] lifecycle events. */ +data class ActivityEventModel( + /** Uniquely identifies an activity. */ + val instanceId: Int, + /** The package name of the source of this event. */ + val packageName: String, + /** The lifecycle change which this event represents. */ + val lifecycle: Lifecycle, + /** The timestamp of the event. Defined in unix time, see [SystemClock.currentTimeMillis] */ + @CurrentTimeMillisLong val timestamp: Long, +) { + enum class Lifecycle { + UNKNOWN, + RESUMED, + PAUSED, + STOPPED, + DESTROYED + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index b7c02ea91a6b..6e01393015ed 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -112,7 +112,11 @@ constructor( communalSceneInteractor.editModeState.value == EditModeState.STARTING || communalSceneInteractor.isLaunchingWidget.value if (!delaySceneTransition) { - communalSceneInteractor.changeScene(nextScene, nextTransition) + communalSceneInteractor.changeScene( + newScene = nextScene, + loggingReason = "KTF syncing", + transitionKey = nextTransition, + ) } } .launchIn(applicationScope) @@ -176,7 +180,10 @@ constructor( if (scene == CommunalScenes.Communal && isDreaming && timeoutJob == null) { // If dreaming starts after timeout has expired, ex. if dream restarts under // the hub, just close the hub immediately. - communalSceneInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene( + CommunalScenes.Blank, + "dream started after timeout", + ) } } } @@ -201,7 +208,10 @@ constructor( bgScope.launch { delay(screenTimeout.milliseconds) if (isDreaming) { - communalSceneInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene( + newScene = CommunalScenes.Blank, + loggingReason = "hub timeout", + ) } timeoutJob = null } diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalMediaModel.kt b/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalMediaModel.kt index 33edb800756d..c46f0d1cfcb6 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalMediaModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalMediaModel.kt @@ -21,21 +21,21 @@ import com.android.systemui.log.table.TableRowLogger /** Data model of media on the communal hub. */ data class CommunalMediaModel( - val hasActiveMediaOrRecommendation: Boolean, + val hasAnyMediaOrRecommendation: Boolean, val createdTimestampMillis: Long = 0L, ) : Diffable<CommunalMediaModel> { companion object { val INACTIVE = CommunalMediaModel( - hasActiveMediaOrRecommendation = false, + hasAnyMediaOrRecommendation = false, ) } override fun logDiffs(prevVal: CommunalMediaModel, row: TableRowLogger) { - if (hasActiveMediaOrRecommendation != prevVal.hasActiveMediaOrRecommendation) { + if (hasAnyMediaOrRecommendation != prevVal.hasAnyMediaOrRecommendation) { row.logChange( columnName = "isMediaActive", - value = hasActiveMediaOrRecommendation, + value = hasAnyMediaOrRecommendation, ) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt index fe9154c192c5..882991aacdbb 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt @@ -80,10 +80,10 @@ constructor( } private fun updateMediaModel(data: MediaData? = null) { - if (mediaDataManager.hasActiveMediaOrRecommendation()) { + if (mediaDataManager.hasAnyMediaOrRecommendation()) { _mediaModel.value = CommunalMediaModel( - hasActiveMediaOrRecommendation = true, + hasAnyMediaOrRecommendation = true, createdTimestampMillis = data?.createdTimestampMillis ?: 0L, ) } else { diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index fbeb71514db4..7181b15138b9 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -329,8 +329,11 @@ constructor( @Deprecated( "Use com.android.systemui.communal.domain.interactor.CommunalSceneInteractor instead" ) - fun changeScene(newScene: SceneKey, transitionKey: TransitionKey? = null) = - communalSceneInteractor.changeScene(newScene, transitionKey) + fun changeScene( + newScene: SceneKey, + loggingReason: String, + transitionKey: TransitionKey? = null + ) = communalSceneInteractor.changeScene(newScene, loggingReason, transitionKey) fun setEditModeOpen(isOpen: Boolean) { _editModeOpen.value = isOpen @@ -513,7 +516,7 @@ constructor( ) // Add UMO - if (mediaHostVisible && media.hasActiveMediaOrRecommendation) { + if (mediaHostVisible && media.hasAnyMediaOrRecommendation) { ongoingContent.add( CommunalContentModel.Umo( createdTimestampMillis = media.createdTimestampMillis, diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt index e45a69599a68..a0b996675331 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt @@ -22,6 +22,7 @@ import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.systemui.communal.data.repository.CommunalSceneRepository import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel +import com.android.systemui.communal.shared.log.CommunalSceneLogger import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.communal.shared.model.EditModeState @@ -29,6 +30,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf +import com.android.systemui.util.kotlin.pairwiseBy import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -42,8 +44,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton @@ -51,7 +53,8 @@ class CommunalSceneInteractor @Inject constructor( @Application private val applicationScope: CoroutineScope, - private val communalSceneRepository: CommunalSceneRepository, + private val repository: CommunalSceneRepository, + private val logger: CommunalSceneLogger, ) { private val _isLaunchingWidget = MutableStateFlow(false) @@ -80,25 +83,39 @@ constructor( */ fun changeScene( newScene: SceneKey, + loggingReason: String, transitionKey: TransitionKey? = null, keyguardState: KeyguardState? = null, ) { - applicationScope.launch { + applicationScope.launch("$TAG#changeScene") { + logger.logSceneChangeRequested( + from = currentScene.value, + to = newScene, + reason = loggingReason, + isInstant = false, + ) notifyListeners(newScene, keyguardState) - communalSceneRepository.changeScene(newScene, transitionKey) + repository.changeScene(newScene, transitionKey) } } /** Immediately snaps to the new scene. */ fun snapToScene( newScene: SceneKey, + loggingReason: String, delayMillis: Long = 0, keyguardState: KeyguardState? = null ) { applicationScope.launch("$TAG#snapToScene") { delay(delayMillis) + logger.logSceneChangeRequested( + from = currentScene.value, + to = newScene, + reason = loggingReason, + isInstant = true, + ) notifyListeners(newScene, keyguardState) - communalSceneRepository.snapToScene(newScene) + repository.snapToScene(newScene) } } @@ -113,13 +130,30 @@ constructor( if (_editModeState.value == EditModeState.STARTING) { return } - changeScene(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) + changeScene( + CommunalScenes.Blank, + "activity start dismissing keyguard", + CommunalTransitionKeys.SimpleFade, + ) } /** * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene]. */ - val currentScene: Flow<SceneKey> = communalSceneRepository.currentScene + val currentScene: StateFlow<SceneKey> = + repository.currentScene + .pairwiseBy(initialValue = repository.currentScene.value) { from, to -> + logger.logSceneChangeCommitted( + from = from, + to = to, + ) + to + } + .stateIn( + scope = applicationScope, + started = SharingStarted.Eagerly, + initialValue = repository.currentScene.value, + ) private val _editModeState = MutableStateFlow<EditModeState?>(null) /** @@ -134,7 +168,13 @@ constructor( /** Transition state of the hub mode. */ val transitionState: StateFlow<ObservableTransitionState> = - communalSceneRepository.transitionState + repository.transitionState + .onEach { logger.logSceneTransition(it) } + .stateIn( + scope = applicationScope, + started = SharingStarted.Eagerly, + initialValue = repository.transitionState.value, + ) /** * Updates the transition state of the hub [SceneTransitionLayout]. @@ -142,7 +182,7 @@ constructor( * Note that you must call is with `null` when the UI is done or risk a memory leak. */ fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { - communalSceneRepository.setTransitionState(transitionState) + repository.setTransitionState(transitionState) } /** Returns a flow that tracks the progress of transitions to the given scene from 0-1. */ diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt index c780aac5aaca..63437525515c 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt @@ -41,6 +41,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -85,25 +87,29 @@ constructor( */ private val nextKeyguardStateInternal = combine( - keyguardInteractor.isAbleToDream, - keyguardInteractor.isKeyguardOccluded, - keyguardInteractor.isKeyguardGoingAway, - ) { dreaming, occluded, keyguardGoingAway -> - if (keyguardGoingAway) { - KeyguardState.GONE - } else if (occluded && !dreaming) { - KeyguardState.OCCLUDED - } else if (dreaming) { - KeyguardState.DREAMING - } else { - KeyguardState.LOCKSCREEN + keyguardInteractor.isAbleToDream, + keyguardInteractor.isKeyguardOccluded, + keyguardInteractor.isKeyguardGoingAway, + keyguardInteractor.isKeyguardShowing, + ) { dreaming, occluded, keyguardGoingAway, keyguardShowing -> + if (keyguardGoingAway) { + KeyguardState.GONE + } else if (occluded && !dreaming) { + KeyguardState.OCCLUDED + } else if (dreaming) { + KeyguardState.DREAMING + } else if (keyguardShowing) { + KeyguardState.LOCKSCREEN + } else { + null + } } - } + .filterNotNull() private val nextKeyguardState: StateFlow<KeyguardState> = combine( repository.nextLockscreenTargetState, - nextKeyguardStateInternal, + nextKeyguardStateInternal.onStart { emit(KeyguardState.LOCKSCREEN) }, ) { override, nextState -> override ?: nextState } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt new file mode 100644 index 000000000000..7453368d0ee7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractor.kt @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import android.app.ActivityManager +import com.android.systemui.common.usagestats.domain.UsageStatsInteractor +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.Logger +import com.android.systemui.log.dagger.CommunalLog +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.shared.system.TaskStackChangeListener +import com.android.systemui.shared.system.TaskStackChangeListeners +import com.android.systemui.util.kotlin.race +import com.android.systemui.util.time.SystemClock +import javax.inject.Inject +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.takeWhile +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withTimeout + +/** + * Detects activity starts that occur while the communal hub is showing, within a short delay of a + * widget interaction occurring. Used for detecting non-activity trampolines which otherwise would + * not prompt the user for authentication. + */ +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton +class WidgetTrampolineInteractor +@Inject +constructor( + private val activityStarter: ActivityStarter, + private val systemClock: SystemClock, + private val keyguardTransitionInteractor: KeyguardTransitionInteractor, + private val taskStackChangeListeners: TaskStackChangeListeners, + private val usageStatsInteractor: UsageStatsInteractor, + @CommunalLog logBuffer: LogBuffer, +) { + private companion object { + const val TAG = "WidgetTrampolineInteractor" + } + + private val logger = Logger(logBuffer, TAG) + + /** Waits for a new task to be moved to the foreground. */ + private suspend fun waitForNewForegroundTask() = suspendCancellableCoroutine { cont -> + val listener = + object : TaskStackChangeListener { + override fun onTaskMovedToFront(taskInfo: ActivityManager.RunningTaskInfo) { + if (!cont.isCompleted) { + cont.resume(Unit, null) + } + } + } + taskStackChangeListeners.registerTaskStackListener(listener) + cont.invokeOnCancellation { taskStackChangeListeners.unregisterTaskStackListener(listener) } + } + + /** + * Waits for an activity to enter a [ActivityEventModel.Lifecycle.RESUMED] state by periodically + * polling the system to see if any activities have started. + */ + private suspend fun waitForActivityStartByPolling(startTime: Long): Boolean { + while (true) { + val events = usageStatsInteractor.queryActivityEvents(startTime = startTime) + if (events.any { event -> event.lifecycle == ActivityEventModel.Lifecycle.RESUMED }) { + return true + } else { + // Poll again in the future to check if an activity started. + delay(200.milliseconds) + } + } + } + + /** Waits for a transition away from the hub to occur. */ + private suspend fun waitForTransitionAwayFromHub() { + keyguardTransitionInteractor + .isFinishedIn(Scenes.Communal, KeyguardState.GLANCEABLE_HUB) + .takeWhile { it } + .collect {} + } + + private suspend fun waitForActivityStartWhileOnHub(): Boolean { + val startTime = systemClock.currentTimeMillis() + return try { + return withTimeout(1.seconds) { + race( + { + waitForNewForegroundTask() + true + }, + { waitForActivityStartByPolling(startTime) }, + { + waitForTransitionAwayFromHub() + false + }, + ) + } + } catch (e: TimeoutCancellationException) { + false + } + } + + /** + * Checks if an activity starts while on the glanceable hub and dismisses the keyguard if it + * does. This can detect activities started due to broadcast trampolines from widgets. + */ + suspend fun waitForActivityStartAndDismissKeyguard() { + if (waitForActivityStartWhileOnHub()) { + logger.d("Detected trampoline, requesting unlock") + activityStarter.dismissKeyguardThenExecute( + /* action= */ { false }, + /* cancel= */ null, + /* afterKeyguardGone= */ false + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt new file mode 100644 index 000000000000..aed92156cfc3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.shared.log + +import com.android.compose.animation.scene.ObservableTransitionState +import com.android.compose.animation.scene.SceneKey +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.dagger.CommunalLog +import javax.inject.Inject + +class CommunalSceneLogger @Inject constructor(@CommunalLog private val logBuffer: LogBuffer) { + + fun logSceneChangeRequested( + from: SceneKey, + to: SceneKey, + reason: String, + isInstant: Boolean, + ) { + logBuffer.log( + tag = TAG, + level = LogLevel.INFO, + messageInitializer = { + str1 = from.toString() + str2 = to.toString() + str3 = reason + bool1 = isInstant + }, + messagePrinter = { + buildString { + append("Scene change requested: $str1 → $str2") + if (isInstant) { + append(" (instant)") + } + append(", reason: $str3") + } + }, + ) + } + + fun logSceneChangeCommitted( + from: SceneKey, + to: SceneKey, + ) { + logBuffer.log( + tag = TAG, + level = LogLevel.INFO, + messageInitializer = { + str1 = from.toString() + str2 = to.toString() + }, + messagePrinter = { "Scene change committed: $str1 → $str2" }, + ) + } + + fun logSceneTransition(transitionState: ObservableTransitionState) { + when (transitionState) { + is ObservableTransitionState.Transition -> { + logBuffer.log( + tag = TAG, + level = LogLevel.INFO, + messageInitializer = { + str1 = transitionState.fromScene.toString() + str2 = transitionState.toScene.toString() + }, + messagePrinter = { "Scene transition started: $str1 → $str2" }, + ) + } + is ObservableTransitionState.Idle -> { + logBuffer.log( + tag = TAG, + level = LogLevel.INFO, + messageInitializer = { str1 = transitionState.currentScene.toString() }, + messagePrinter = { "Scene transition idle on: $str1" }, + ) + } + } + } + + companion object { + private const val TAG = "CommunalSceneLogger" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt index c4edcac1a2a1..99e3232a70c2 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/smartspace/SmartspaceInteractionHandler.kt @@ -48,7 +48,17 @@ constructor( InteractionHandlerDelegate( communalSceneInteractor, findViewToAnimate = { view -> view is SmartspaceAppWidgetHostView }, - intentStarter = this::startIntent, + intentStarter = + object : InteractionHandlerDelegate.IntentStarter { + override fun startActivity( + intent: PendingIntent, + fillInIntent: Intent, + activityOptions: ActivityOptions, + controller: ActivityTransitionAnimator.Controller? + ): Boolean { + return startIntent(intent, fillInIntent, activityOptions, controller) + } + }, logger = Logger(logBuffer, TAG), ) diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt index 7a0567190bd0..5f421fd19550 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt @@ -21,10 +21,13 @@ import android.util.SizeF import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.core.view.doOnLayout import com.android.app.tracing.coroutines.launch import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.util.WidgetViewFactory import com.android.systemui.util.kotlin.DisposableHandles +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle @@ -44,13 +47,8 @@ object CommunalAppWidgetHostViewBinder { val loadingJob = applicationScope.launch("$TAG#createWidgetView") { val widget = factory.createWidget(context, model, size) - // TODO(b/358662507): Remove this workaround - (container.parent as? ViewGroup)?.let { parent -> - val index = parent.indexOfChild(container) - parent.removeView(container) - parent.addView(container, index) - } - container.setView(widget) + waitForLayout(container) + container.post { container.setView(widget) } } disposables += DisposableHandle { loadingJob.cancel() } @@ -58,6 +56,10 @@ object CommunalAppWidgetHostViewBinder { return disposables } + + private suspend fun waitForLayout(container: FrameLayout) = suspendCoroutine { cont -> + container.doOnLayout { cont.resume(Unit) } + } } private fun ViewGroup.setView(view: View) { diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt index d1a5a4b8641f..b8221332eadf 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt @@ -106,10 +106,11 @@ abstract class BaseCommunalViewModel( */ fun changeScene( scene: SceneKey, + loggingReason: String, transitionKey: TransitionKey? = null, keyguardState: KeyguardState? = null ) { - communalSceneInteractor.changeScene(scene, transitionKey, keyguardState) + communalSceneInteractor.changeScene(scene, loggingReason, transitionKey, keyguardState) } fun setEditModeState(state: EditModeState?) = communalSceneInteractor.setEditModeState(state) diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt index bbd8596a76bd..623937305921 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt @@ -67,7 +67,10 @@ constructor( * transition. */ fun snapToCommunal() { - communalSceneInteractor.snapToScene(CommunalScenes.Communal) + communalSceneInteractor.snapToScene( + newScene = CommunalScenes.Communal, + loggingReason = "transition view model", + ) } // Show UMO on glanceable hub immediately on transition into glanceable hub diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt index b06cf3ffcf45..c0a18f29149d 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt @@ -252,7 +252,7 @@ constructor( with(mediaHost) { expansion = MediaHostState.EXPANDED expandedMatchesParentHeight = true - showsOnlyActiveMedia = true + showsOnlyActiveMedia = false falsingProtectionNeeded = false init(MediaHierarchyManager.LOCATION_COMMUNAL_HUB) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt index d2029d50bf63..5e21afacf9f3 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/util/InteractionHandlerDelegate.kt @@ -19,6 +19,7 @@ package com.android.systemui.communal.util import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent +import android.util.Pair as UtilPair import android.view.View import android.widget.RemoteViews import androidx.core.util.component1 @@ -36,14 +37,28 @@ class InteractionHandlerDelegate( private val logger: Logger, ) : RemoteViews.InteractionHandler { - /** Responsible for starting the pending intent for launching activities. */ - fun interface IntentStarter { - fun startPendingIntent( + interface IntentStarter { + /** Responsible for starting the pending intent for launching activities. */ + fun startActivity( intent: PendingIntent, fillInIntent: Intent, activityOptions: ActivityOptions, controller: ActivityTransitionAnimator.Controller?, ): Boolean + + /** Responsible for starting the pending intent for non-activity launches. */ + fun startPendingIntent( + view: View, + pendingIntent: PendingIntent, + fillInIntent: Intent, + activityOptions: ActivityOptions, + ): Boolean { + return RemoteViews.startPendingIntent( + view, + pendingIntent, + UtilPair(fillInIntent, activityOptions), + ) + } } override fun onInteraction( @@ -55,7 +70,7 @@ class InteractionHandlerDelegate( str1 = pendingIntent.toLoggingString() str2 = pendingIntent.creatorPackage } - val launchOptions = response.getLaunchOptions(view) + val (fillInIntent, activityOptions) = response.getLaunchOptions(view) return when { pendingIntent.isActivity -> { // Forward the fill-in intent and activity options retrieved from the response @@ -67,15 +82,15 @@ class InteractionHandlerDelegate( communalSceneInteractor.setIsLaunchingWidget(true) CommunalTransitionAnimatorController(it, communalSceneInteractor) } - val (fillInIntent, activityOptions) = launchOptions - intentStarter.startPendingIntent( + intentStarter.startActivity( pendingIntent, fillInIntent, activityOptions, animationController ) } - else -> RemoteViews.startPendingIntent(view, pendingIntent, launchOptions) + else -> + intentStarter.startPendingIntent(view, pendingIntent, fillInIntent, activityOptions) } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt index 08444623f24d..e7cedc61610f 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt @@ -42,6 +42,7 @@ class CommunalTransitionAnimatorController( // TODO(b/330672236): move this to onTransitionAnimationEnd() without the delay. communalSceneInteractor.snapToScene( CommunalScenes.Blank, + "CommunalTransitionAnimatorController", ActivityTransitionAnimator.TIMINGS.totalDuration ) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt index 668fef6130bb..b421e5932352 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt @@ -16,10 +16,7 @@ package com.android.systemui.communal.widgets -import android.app.Activity -import android.app.Application.ActivityLifecycleCallbacks import android.content.Intent -import android.content.IntentSender import android.os.Bundle import android.os.RemoteException import android.util.Log @@ -71,78 +68,12 @@ constructor( const val EXTRA_OPEN_WIDGET_PICKER_ON_START = "open_widget_picker_on_start" } - /** - * [ActivityController] handles closing the activity in the case it is backgrounded without - * waiting for an activity result - */ - class ActivityController(activity: Activity) { - companion object { - private const val STATE_EXTRA_IS_WAITING_FOR_RESULT = "extra_is_waiting_for_result" - } - - private var waitingForResult: Boolean = false - - init { - activity.registerActivityLifecycleCallbacks( - object : ActivityLifecycleCallbacks { - override fun onActivityCreated( - activity: Activity, - savedInstanceState: Bundle? - ) { - waitingForResult = - savedInstanceState?.getBoolean(STATE_EXTRA_IS_WAITING_FOR_RESULT) - ?: false - } - - override fun onActivityStarted(activity: Activity) { - // Nothing to implement. - } - - override fun onActivityResumed(activity: Activity) { - // Nothing to implement. - } - - override fun onActivityPaused(activity: Activity) { - // Nothing to implement. - } - - override fun onActivityStopped(activity: Activity) { - // If we're not backgrounded due to waiting for a resul (either widget - // selection - // or configuration), finish activity. - if (!waitingForResult) { - activity.finish() - } - } - - override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { - outState.putBoolean(STATE_EXTRA_IS_WAITING_FOR_RESULT, waitingForResult) - } - - override fun onActivityDestroyed(activity: Activity) { - // Nothing to implement. - } - } - ) - } - - /** - * Invoked when waiting for an activity result changes, either initiating such wait or - * finishing due to the return of a result. - */ - fun onWaitingForResult(waitingForResult: Boolean) { - this.waitingForResult = waitingForResult - } - } - private val logger = Logger(logBuffer, "EditWidgetsActivity") private val widgetConfigurator by lazy { widgetConfiguratorFactory.create(this) } private var shouldOpenWidgetPickerOnStart = false - private val activityController: ActivityController = ActivityController(this) - private val addWidgetActivityLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(StartActivityForResult()) { result -> when (result.resultCode) { @@ -218,9 +149,10 @@ constructor( lifecycleScope.launch { communalViewModel.canShowEditMode.collect { communalViewModel.changeScene( - CommunalScenes.Blank, - CommunalTransitionKeys.ToEditMode, - KeyguardState.GONE, + scene = CommunalScenes.Blank, + loggingReason = "edit mode opening", + transitionKey = CommunalTransitionKeys.ToEditMode, + keyguardState = KeyguardState.GONE, ) // wait till transitioned to Blank scene, then animate in communal content in // edit mode @@ -252,8 +184,9 @@ constructor( communalViewModel.cleanupEditModeState() communalViewModel.changeScene( - CommunalScenes.Communal, - CommunalTransitionKeys.FromEditMode + scene = CommunalScenes.Communal, + loggingReason = "edit mode closing", + transitionKey = CommunalTransitionKeys.FromEditMode ) // Wait for the current scene to be idle on communal. @@ -265,34 +198,7 @@ constructor( } } - override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) { - activityController.onWaitingForResult(true) - super.startActivityForResult(intent, requestCode, options) - } - - override fun startIntentSenderForResult( - intent: IntentSender, - requestCode: Int, - fillInIntent: Intent?, - flagsMask: Int, - flagsValues: Int, - extraFlags: Int, - options: Bundle? - ) { - activityController.onWaitingForResult(true) - super.startIntentSenderForResult( - intent, - requestCode, - fillInIntent, - flagsMask, - flagsValues, - extraFlags, - options - ) - } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - activityController.onWaitingForResult(false) super.onActivityResult(requestCode, resultCode, data) if (requestCode == WidgetConfigurationController.REQUEST_CODE) { widgetConfigurator.setConfigurationResult(resultCode) diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt index 0eeb506ccc09..542b98896986 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt @@ -21,22 +21,35 @@ import android.app.PendingIntent import android.content.Intent import android.view.View import android.widget.RemoteViews +import com.android.app.tracing.coroutines.launch +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.Flags.communalWidgetTrampolineFix import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor +import com.android.systemui.communal.domain.interactor.WidgetTrampolineInteractor import com.android.systemui.communal.util.InteractionHandlerDelegate import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.UiBackground import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.CommunalLog import com.android.systemui.plugins.ActivityStarter import javax.inject.Inject +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job @SysUISingleton class WidgetInteractionHandler @Inject constructor( + @Application private val applicationScope: CoroutineScope, + @UiBackground private val uiBackgroundContext: CoroutineContext, private val activityStarter: ActivityStarter, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, communalSceneInteractor: CommunalSceneInteractor, + private val widgetTrampolineInteractor: WidgetTrampolineInteractor, @CommunalLog val logBuffer: LogBuffer, ) : RemoteViews.InteractionHandler { @@ -48,7 +61,52 @@ constructor( InteractionHandlerDelegate( communalSceneInteractor, findViewToAnimate = { view -> view is CommunalAppWidgetHostView }, - intentStarter = this::startIntent, + intentStarter = + object : InteractionHandlerDelegate.IntentStarter { + private var job: Job? = null + + override fun startActivity( + intent: PendingIntent, + fillInIntent: Intent, + activityOptions: ActivityOptions, + controller: ActivityTransitionAnimator.Controller? + ): Boolean { + cancelTrampolineMonitoring() + return startActivityIntent( + intent, + fillInIntent, + activityOptions, + controller + ) + } + + override fun startPendingIntent( + view: View, + pendingIntent: PendingIntent, + fillInIntent: Intent, + activityOptions: ActivityOptions + ): Boolean { + cancelTrampolineMonitoring() + if (communalWidgetTrampolineFix()) { + job = + applicationScope.launch("$TAG#monitorForActivityStart") { + widgetTrampolineInteractor + .waitForActivityStartAndDismissKeyguard() + } + } + return super.startPendingIntent( + view, + pendingIntent, + fillInIntent, + activityOptions + ) + } + + private fun cancelTrampolineMonitoring() { + job?.cancel() + job = null + } + }, logger = Logger(logBuffer, TAG), ) @@ -58,7 +116,7 @@ constructor( response: RemoteViews.RemoteResponse ): Boolean = delegate.onInteraction(view, pendingIntent, response) - private fun startIntent( + private fun startActivityIntent( pendingIntent: PendingIntent, fillInIntent: Intent, extraOptions: ActivityOptions, @@ -67,7 +125,14 @@ constructor( activityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, /* dismissShade = */ false, - /* intentSentUiThreadCallback = */ null, + { + applicationScope.launch("$TAG#awakenFromDream", uiBackgroundContext) { + // This activity could have started while the device is dreaming, in which case + // the dream would occlude the activity. In order to show the newly started + // activity, we wake from the dream. + keyguardUpdateMonitor.awakenFromDream() + } + }, controller, fillInIntent, extraOptions.toBundle(), diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt index 74e1dc0b0fad..a5f29aa658be 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt @@ -38,31 +38,35 @@ import com.android.systemui.util.ActivityTaskManagerProxy import com.android.systemui.util.asIndenting import com.android.systemui.util.indentIfPossible import java.io.PrintWriter +import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject private fun createServiceListing(context: Context): ServiceListing { - return ServiceListing.Builder(context).apply { - setIntentAction(ControlsProviderService.SERVICE_CONTROLS) - setPermission("android.permission.BIND_CONTROLS") - setNoun("Controls Provider") - setSetting("controls_providers") - setTag("controls_providers") - setAddDeviceLockedFlags(true) - }.build() + return ServiceListing.Builder(context) + .apply { + setIntentAction(ControlsProviderService.SERVICE_CONTROLS) + setPermission("android.permission.BIND_CONTROLS") + setNoun("Controls Provider") + setSetting("controls_providers") + setTag("controls_providers") + setAddDeviceLockedFlags(true) + } + .build() } /** * Provides a listing of components to be used as ControlsServiceProvider. * * This controller keeps track of components that satisfy: - * * * Has an intent-filter responding to [ControlsProviderService.CONTROLS_ACTION] * * Has the bind permission `android.permission.BIND_CONTROLS` */ @SysUISingleton -class ControlsListingControllerImpl @VisibleForTesting constructor( +class ControlsListingControllerImpl +@VisibleForTesting +constructor( private val context: Context, @Background private val backgroundExecutor: Executor, private val serviceListingBuilder: (Context) -> ServiceListing, @@ -74,12 +78,12 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( @Inject constructor( - context: Context, - @Background executor: Executor, - userTracker: UserTracker, - activityTaskManagerProxy: ActivityTaskManagerProxy, - dumpManager: DumpManager, - featureFlags: FeatureFlags + context: Context, + @Background executor: Executor, + userTracker: UserTracker, + activityTaskManagerProxy: ActivityTaskManagerProxy, + dumpManager: DumpManager, + featureFlags: FeatureFlags ) : this( context, executor, @@ -92,7 +96,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( private var serviceListing = serviceListingBuilder(context) // All operations in background thread - private val callbacks = mutableSetOf<ControlsListingController.ControlsListingCallback>() + private val callbacks = CopyOnWriteArraySet<ControlsListingController.ControlsListingCallback>() companion object { private const val TAG = "ControlsListingControllerImpl" @@ -104,15 +108,17 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( override var currentUserId = userTracker.userId private set - private val serviceListingCallback = ServiceListing.Callback { list -> - Log.d(TAG, "ServiceConfig reloaded, count: ${list.size}") - val newServices = list.map { ControlsServiceInfo(userTracker.userContext, it) } - // After here, `list` is not captured, so we don't risk modifying it outside of the callback - backgroundExecutor.execute { - if (userChangeInProgress.get() > 0) return@execute - updateServices(newServices) + private val serviceListingCallback = + ServiceListing.Callback { list -> + Log.d(TAG, "ServiceConfig reloaded, count: ${list.size}") + val newServices = list.map { ControlsServiceInfo(userTracker.userContext, it) } + // After here, `list` is not captured, so we don't risk modifying it outside of the + // callback + backgroundExecutor.execute { + if (userChangeInProgress.get() > 0) return@execute + updateServices(newServices) + } } - } init { Log.d(TAG, "Initializing") @@ -124,15 +130,12 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( private fun updateServices(newServices: List<ControlsServiceInfo>) { if (activityTaskManagerProxy.supportsMultiWindow(context)) { - newServices.forEach { - it.resolvePanelActivity() } + newServices.forEach { it.resolvePanelActivity() } } if (newServices != availableServices) { availableServices = newServices - callbacks.forEach { - it.onServicesUpdated(getCurrentServices()) - } + callbacks.forEach { it.onServicesUpdated(getCurrentServices()) } } } @@ -155,8 +158,8 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( /** * Adds a callback to this controller. * - * The callback will be notified after it is added as well as any time that the valid - * components change. + * The callback will be notified after it is added as well as any time that the valid components + * change. * * @param listener a callback to be notified */ @@ -188,26 +191,29 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( } /** - * @return a list of components that satisfy the requirements to be a - * [ControlsProviderService] + * @return a list of components that satisfy the requirements to be a [ControlsProviderService] */ override fun getCurrentServices(): List<ControlsServiceInfo> = - availableServices.map(ControlsServiceInfo::copy) + availableServices.map(ControlsServiceInfo::copy) @WorkerThread override fun forceReload() { val packageManager = context.packageManager val intent = Intent(ControlsProviderService.SERVICE_CONTROLS) val user = userTracker.userHandle - val flags = PackageManager.GET_SERVICES or + val flags = + PackageManager.GET_SERVICES or PackageManager.GET_META_DATA or PackageManager.MATCH_DIRECT_BOOT_UNAWARE or PackageManager.MATCH_DIRECT_BOOT_AWARE - val services = packageManager.queryIntentServicesAsUser( - intent, - PackageManager.ResolveInfoFlags.of(flags.toLong()), - user - ).map { ControlsServiceInfo(userTracker.userContext, it.serviceInfo) } + val services = + packageManager + .queryIntentServicesAsUser( + intent, + PackageManager.ResolveInfoFlags.of(flags.toLong()), + user + ) + .map { ControlsServiceInfo(userTracker.userContext, it.serviceInfo) } updateServices(services) } @@ -218,8 +224,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( * @return a label as returned by [CandidateInfo.loadLabel] or `null`. */ override fun getAppLabel(name: ComponentName): CharSequence? { - return availableServices.firstOrNull { it.componentName == name } - ?.loadLabel() + return availableServices.firstOrNull { it.componentName == name }?.loadLabel() } override fun dump(writer: PrintWriter, args: Array<out String>) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index 2ea27b76d81b..21a704df074e 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -42,6 +42,7 @@ import android.app.job.JobScheduler; import android.app.role.RoleManager; import android.app.smartspace.SmartspaceManager; import android.app.trust.TrustManager; +import android.app.usage.UsageStatsManager; import android.appwidget.AppWidgetManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; @@ -544,6 +545,13 @@ public class FrameworkServicesModule { return context.getSystemService(UiModeManager.class); } + /** */ + @Provides + @Singleton + static UsageStatsManager provideUsageStatsManager(Context context) { + return context.getSystemService(UsageStatsManager.class); + } + @Provides @Main static Resources provideResources(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 25b6b14049a6..0363a684ec67 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -48,6 +48,7 @@ import com.android.systemui.brightness.dagger.ScreenBrightnessModule; import com.android.systemui.classifier.FalsingModule; import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule; import com.android.systemui.common.data.CommonDataLayerModule; +import com.android.systemui.common.usagestats.data.CommonUsageStatsDataLayerModule; import com.android.systemui.communal.dagger.CommunalModule; import com.android.systemui.complication.dagger.ComplicationComponent; import com.android.systemui.controls.dagger.ControlsModule; @@ -205,6 +206,7 @@ import javax.inject.Named; ClockRegistryModule.class, CommunalModule.class, CommonDataLayerModule.class, + CommonUsageStatsDataLayerModule.class, ConfigurationControllerModule.class, ConnectivityModule.class, ControlsModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt index e4b290d7d10e..15a3cbdb8072 100644 --- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt @@ -17,7 +17,6 @@ package com.android.systemui.display.domain.interactor import android.companion.virtual.VirtualDeviceManager -import android.companion.virtual.flags.Flags import android.view.Display import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -155,8 +154,7 @@ constructor( } private fun isVirtualDeviceOwnedMirrorDisplay(display: Display): Boolean { - return Flags.interactiveScreenMirror() && - virtualDeviceManager != null && + return virtualDeviceManager != null && virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(display.displayId) } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 4b9e5a024393..0c1fb72cc581 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -442,7 +442,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ @Override public void onWakeRequested() { mUiEventLogger.log(CommunalUiEvent.DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START); - mCommunalInteractor.changeScene(CommunalScenes.Communal, null); + mCommunalInteractor.changeScene(CommunalScenes.Communal, + "dream wake requested", + null); } private Lifecycle.State getLifecycleStateLocked() { @@ -493,7 +495,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mSystemDialogsCloser.closeSystemDialogs(); // Hide glanceable hub (this is a nop if glanceable hub is not open). - mCommunalInteractor.changeScene(CommunalScenes.Blank, null); + mCommunalInteractor.changeScene(CommunalScenes.Blank, "dream come to front", null); } /** diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt index 4b07f78eb825..5c0335a6dfae 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt @@ -20,9 +20,9 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Flags.glanceableHubAllowKeyguardWhenDreaming import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager +import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING @@ -51,6 +51,7 @@ constructor( fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, + private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor, private val communalInteractor: CommunalInteractor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val userTracker: UserTracker, @@ -61,11 +62,9 @@ constructor( val showGlanceableHub = communalInteractor.isCommunalEnabled.value && !keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId) - if (showGlanceableHub && !glanceableHubAllowKeyguardWhenDreaming()) { - communalInteractor.changeScene(CommunalScenes.Communal) - } else { - toLockscreenTransitionViewModel.startTransition() - } + fromDreamingTransitionInteractor.startToLockscreenOrGlanceableHubTransition( + showGlanceableHub && !glanceableHubAllowKeyguardWhenDreaming() + ) } val dreamOverlayTranslationX: Flow<Float> = diff --git a/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt b/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt index a171f8775768..1daaa1128ba0 100644 --- a/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt @@ -28,4 +28,5 @@ data class GestureEduModel( val lastShortcutTriggeredTime: Instant? = null, val usageSessionStartTime: Instant? = null, val lastEducationTime: Instant? = null, + val userId: Int ) diff --git a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt index 7c3d63388aa1..4fd79d764cdd 100644 --- a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt @@ -33,6 +33,7 @@ import com.android.systemui.education.data.model.GestureEduModel import java.time.Instant import javax.inject.Inject import javax.inject.Provider +import kotlin.properties.Delegates.notNull import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.Flow @@ -79,6 +80,8 @@ constructor( const val DATASTORE_DIR = "education/USER%s_ContextualEducation" } + private var userId by notNull<Int>() + private var dataStoreScope: CoroutineScope? = null private val datastore = MutableStateFlow<DataStore<Preferences>?>(null) @@ -89,6 +92,7 @@ constructor( override fun setUser(userId: Int) { dataStoreScope?.cancel() val newDsScope = dataStoreScopeProvider.get() + this.userId = userId datastore.value = PreferenceDataStoreFactory.create( produceFile = { @@ -123,6 +127,7 @@ constructor( preferences[getLastEducationTimeKey(gestureType)]?.let { Instant.ofEpochSecond(it) }, + userId = userId ) } diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt index 3a3fb8c6acbe..ad3335b7cdeb 100644 --- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt @@ -56,7 +56,7 @@ constructor( if (isUsageSessionExpired(it)) { contextualEducationInteractor.startNewUsageSession(BACK) } else if (isEducationNeeded(it)) { - _educationTriggered.value = EducationInfo(BACK, getEduType(it)) + _educationTriggered.value = EducationInfo(BACK, getEduType(it), it.userId) contextualEducationInteractor.updateOnEduTriggered(BACK) } } diff --git a/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt b/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt index d92fb9bff512..27c41cffc808 100644 --- a/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/education/shared/model/EducationInfo.kt @@ -22,7 +22,11 @@ import com.android.systemui.contextualeducation.GestureType * Model for education triggered. [gestureType] indicates what gesture it is trying to educate about * and [educationUiType] is how we educate user in the UI */ -data class EducationInfo(val gestureType: GestureType, val educationUiType: EducationUiType) +data class EducationInfo( + val gestureType: GestureType, + val educationUiType: EducationUiType, + val userId: Int +) enum class EducationUiType { Toast, diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt index b446ea2bcb38..e62b26bfe53d 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduUiCoordinator.kt @@ -16,14 +16,24 @@ package com.android.systemui.education.ui.view +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.UserHandle import android.widget.Toast +import androidx.core.app.NotificationCompat import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.education.shared.model.EducationUiType -import com.android.systemui.education.ui.viewmodel.ContextualEduContentViewModel +import com.android.systemui.education.ui.viewmodel.ContextualEduNotificationViewModel +import com.android.systemui.education.ui.viewmodel.ContextualEduToastViewModel import com.android.systemui.education.ui.viewmodel.ContextualEduViewModel +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity +import com.android.systemui.res.R import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -37,32 +47,96 @@ class ContextualEduUiCoordinator constructor( @Application private val applicationScope: CoroutineScope, private val viewModel: ContextualEduViewModel, + private val context: Context, + private val notificationManager: NotificationManager, private val createToast: (String) -> Toast ) : CoreStartable { + companion object { + private const val CHANNEL_ID = "ContextualEduNotificationChannel" + private const val TAG = "ContextualEduUiCoordinator" + private const val NOTIFICATION_ID = 1000 + } + @Inject constructor( @Application applicationScope: CoroutineScope, context: Context, viewModel: ContextualEduViewModel, + notificationManager: NotificationManager, ) : this( applicationScope, viewModel, + context, + notificationManager, createToast = { message -> Toast.makeText(context, message, Toast.LENGTH_LONG) } ) override fun start() { + createEduNotificationChannel() applicationScope.launch { viewModel.eduContent.collect { contentModel -> - if (contentModel.type == EducationUiType.Toast) { - showToast(contentModel) + when (contentModel) { + is ContextualEduToastViewModel -> showToast(contentModel) + is ContextualEduNotificationViewModel -> showNotification(contentModel) } } } } - private fun showToast(model: ContextualEduContentViewModel) { + private fun createEduNotificationChannel() { + val channel = + NotificationChannel( + CHANNEL_ID, + context.getString(com.android.internal.R.string.android_system_label), + // Make it as silent notification + NotificationManager.IMPORTANCE_LOW + ) + notificationManager.createNotificationChannel(channel) + } + + private fun showToast(model: ContextualEduToastViewModel) { val toast = createToast(model.message) toast.show() } + + private fun showNotification(model: ContextualEduNotificationViewModel) { + // Replace "System UI" app name with "Android System" + val extras = Bundle() + extras.putString( + Notification.EXTRA_SUBSTITUTE_APP_NAME, + context.getString(com.android.internal.R.string.android_system_label) + ) + + val notification = + NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_settings) + .setContentTitle(model.title) + .setContentText(model.message) + .setContentIntent(createPendingIntent()) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true) + .addExtras(extras) + .build() + notificationManager.notifyAsUser( + TAG, + NOTIFICATION_ID, + notification, + UserHandle.of(model.userId) + ) + } + + private fun createPendingIntent(): PendingIntent { + val intent = + Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply { + addCategory(Intent.CATEGORY_DEFAULT) + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + return PendingIntent.getActivity( + context, + /* requestCode= */ 0, + intent, + PendingIntent.FLAG_IMMUTABLE + ) + } } diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt index 3cba4c8fb110..632b250512cb 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt @@ -16,6 +16,13 @@ package com.android.systemui.education.ui.viewmodel -import com.android.systemui.education.shared.model.EducationUiType +sealed class ContextualEduContentViewModel(open val userId: Int) -data class ContextualEduContentViewModel(val message: String, val type: EducationUiType) +data class ContextualEduNotificationViewModel( + val title: String, + val message: String, + override val userId: Int +) : ContextualEduContentViewModel(userId) + +data class ContextualEduToastViewModel(val message: String, override val userId: Int) : + ContextualEduContentViewModel(userId) diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt index 58276e0759f6..cd4a8ad8dbda 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt @@ -17,11 +17,15 @@ package com.android.systemui.education.ui.viewmodel import android.content.res.Resources -import com.android.systemui.contextualeducation.GestureType +import com.android.systemui.contextualeducation.GestureType.ALL_APPS +import com.android.systemui.contextualeducation.GestureType.BACK +import com.android.systemui.contextualeducation.GestureType.HOME +import com.android.systemui.contextualeducation.GestureType.OVERVIEW import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduInteractor import com.android.systemui.education.shared.model.EducationInfo +import com.android.systemui.education.shared.model.EducationUiType import com.android.systemui.res.R import javax.inject.Inject import kotlinx.coroutines.flow.Flow @@ -34,18 +38,43 @@ class ContextualEduViewModel constructor(@Main private val resources: Resources, interactor: KeyboardTouchpadEduInteractor) { val eduContent: Flow<ContextualEduContentViewModel> = interactor.educationTriggered.filterNotNull().map { - ContextualEduContentViewModel(getEduContent(it), it.educationUiType) + if (it.educationUiType == EducationUiType.Notification) { + ContextualEduNotificationViewModel(getEduTitle(it), getEduContent(it), it.userId) + } else { + ContextualEduToastViewModel(getEduContent(it), it.userId) + } } private fun getEduContent(educationInfo: EducationInfo): String { - // Todo: also check UiType in educationInfo to determine the string + val resourceId = + if (educationInfo.educationUiType == EducationUiType.Notification) { + when (educationInfo.gestureType) { + BACK -> R.string.back_edu_notification_content + HOME -> R.string.home_edu_notification_content + OVERVIEW -> R.string.overview_edu_notification_content + ALL_APPS -> R.string.all_apps_edu_notification_content + } + } else { + when (educationInfo.gestureType) { + BACK -> R.string.back_edu_toast_content + HOME -> R.string.home_edu_toast_content + OVERVIEW -> R.string.overview_edu_toast_content + ALL_APPS -> R.string.all_apps_edu_toast_content + } + } + + return resources.getString(resourceId) + } + + private fun getEduTitle(educationInfo: EducationInfo): String { val resourceId = when (educationInfo.gestureType) { - GestureType.BACK -> R.string.back_edu_toast_content - GestureType.HOME -> R.string.home_edu_toast_content - GestureType.OVERVIEW -> R.string.overview_edu_toast_content - GestureType.ALL_APPS -> R.string.all_apps_edu_toast_content + BACK -> R.string.back_edu_notification_title + HOME -> R.string.home_edu_notification_title + OVERVIEW -> R.string.overview_edu_notification_title + ALL_APPS -> R.string.all_apps_edu_notification_title } + return resources.getString(resourceId) } } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt deleted file mode 100644 index 3e382d669e5d..000000000000 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.inputdevice.tutorial.ui.view - -import android.os.Bundle -import android.view.WindowManager -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.activity.viewModels -import androidx.compose.runtime.Composable -import com.android.compose.theme.PlatformTheme -import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider -import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel -import java.util.Optional -import javax.inject.Inject - -/** - * Activity for out of the box experience for keyboard and touchpad. Note that it's possible that - * either of them are actually not connected when this is launched - */ -class KeyboardTouchpadTutorialActivity -@Inject -constructor( - private val viewModelFactory: KeyboardTouchpadTutorialViewModel.Factory, - private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>, -) : ComponentActivity() { - - private val vm by - viewModels<KeyboardTouchpadTutorialViewModel>(factoryProducer = { viewModelFactory }) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - PlatformTheme { - KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) { finish() } - } - } - // required to handle 3+ fingers on touchpad - window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) - } - - override fun onResume() { - super.onResume() - vm.onOpened() - } - - override fun onPause() { - super.onPause() - vm.onClosed() - } -} - -@Composable -fun KeyboardTouchpadTutorialContainer( - vm: KeyboardTouchpadTutorialViewModel, - touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>, - closeTutorial: () -> Unit -) {} diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt deleted file mode 100644 index 39b1ec0f0390..000000000000 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.inputdevice.tutorial.ui.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor -import java.util.Optional -import javax.inject.Inject -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow - -class KeyboardTouchpadTutorialViewModel( - private val gesturesInteractor: Optional<TouchpadGesturesInteractor> -) : ViewModel() { - - private val _screen = MutableStateFlow(Screen.BACK_GESTURE) - val screen: StateFlow<Screen> = _screen - - fun goTo(screen: Screen) { - _screen.value = screen - } - - fun onOpened() { - gesturesInteractor.ifPresent { it.disableGestures() } - } - - fun onClosed() { - gesturesInteractor.ifPresent { it.enableGestures() } - } - - class Factory - @Inject - constructor(private val gesturesInteractor: Optional<TouchpadGesturesInteractor>) : - ViewModelProvider.Factory { - - @Suppress("UNCHECKED_CAST") - override fun <T : ViewModel> create(modelClass: Class<T>): T { - return KeyboardTouchpadTutorialViewModel(gesturesInteractor) as T - } - } -} - -enum class Screen { - BACK_GESTURE, - HOME_GESTURE, - ACTION_KEY -} diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadTutorialModule.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialModule.kt index 8e6cb077a25e..8e6cb077a25e 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadTutorialModule.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialModule.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/TouchpadTutorialScreensProvider.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt index bd3e771f40bc..bd3e771f40bc 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/TouchpadTutorialScreensProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt index 9f46846f0d91..1dbe83aeb64f 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt @@ -16,7 +16,23 @@ package com.android.systemui.inputdevice.tutorial.data.model -data class DeviceSchedulerInfo(var isLaunched: Boolean = false, var connectTime: Long? = null) { +import java.time.Instant + +data class DeviceSchedulerInfo( + var launchTime: Instant? = null, + var firstConnectionTime: Instant? = null +) { + constructor( + launchTimeSec: Long?, + firstConnectionTimeSec: Long? + ) : this( + launchTimeSec?.let { Instant.ofEpochSecond(it) }, + firstConnectionTimeSec?.let { Instant.ofEpochSecond(it) } + ) + val wasEverConnected: Boolean - get() = connectTime != null + get() = firstConnectionTime != null + + val isLaunched: Boolean + get() = launchTime != null } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt index b9b38954784e..d8d4bd686f07 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt @@ -17,9 +17,9 @@ package com.android.systemui.inputdevice.tutorial.data.repository import android.content.Context +import androidx.annotation.VisibleForTesting import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.preferencesDataStore @@ -27,39 +27,47 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.inputdevice.tutorial.data.model.DeviceSchedulerInfo +import java.time.Instant import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @SysUISingleton -class TutorialSchedulerRepository -@Inject -constructor( - @Application private val applicationContext: Context, - @Background private val backgroundScope: CoroutineScope +class TutorialSchedulerRepository( + private val applicationContext: Context, + backgroundScope: CoroutineScope, + dataStoreName: String ) { + @Inject + constructor( + @Application applicationContext: Context, + @Background backgroundScope: CoroutineScope + ) : this(applicationContext, backgroundScope, dataStoreName = DATASTORE_NAME) private val Context.dataStore: DataStore<Preferences> by - preferencesDataStore(name = DATASTORE_NAME, scope = backgroundScope) + preferencesDataStore(name = dataStoreName, scope = backgroundScope) suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched + suspend fun launchTime(deviceType: DeviceType): Instant? = loadData()[deviceType]!!.launchTime + suspend fun wasEverConnected(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.wasEverConnected - suspend fun connectTime(deviceType: DeviceType): Long = loadData()[deviceType]!!.connectTime!! + suspend fun firstConnectionTime(deviceType: DeviceType): Instant? = + loadData()[deviceType]!!.firstConnectionTime private suspend fun loadData(): Map<DeviceType, DeviceSchedulerInfo> { return applicationContext.dataStore.data.map { pref -> getSchedulerInfo(pref) }.first() } - suspend fun updateConnectTime(device: DeviceType, time: Long) { - applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time } + suspend fun updateFirstConnectionTime(device: DeviceType, time: Instant) { + applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time.epochSecond } } - suspend fun updateLaunch(device: DeviceType) { - applicationContext.dataStore.edit { pref -> pref[getLaunchedKey(device)] = true } + suspend fun updateLaunchTime(device: DeviceType, time: Instant) { + applicationContext.dataStore.edit { pref -> pref[getLaunchKey(device)] = time.epochSecond } } private fun getSchedulerInfo(pref: Preferences): Map<DeviceType, DeviceSchedulerInfo> { @@ -70,21 +78,26 @@ constructor( } private fun getDeviceSchedulerInfo(pref: Preferences, device: DeviceType): DeviceSchedulerInfo { - val isLaunched = pref[getLaunchedKey(device)] ?: false - val connectionTime = pref[getConnectKey(device)] ?: null - return DeviceSchedulerInfo(isLaunched, connectionTime) + val launchTime = pref[getLaunchKey(device)] + val connectionTime = pref[getConnectKey(device)] + return DeviceSchedulerInfo(launchTime, connectionTime) } - private fun getLaunchedKey(device: DeviceType) = - booleanPreferencesKey(device.name + IS_LAUNCHED_SUFFIX) + private fun getLaunchKey(device: DeviceType) = + longPreferencesKey(device.name + LAUNCH_TIME_SUFFIX) private fun getConnectKey(device: DeviceType) = longPreferencesKey(device.name + CONNECT_TIME_SUFFIX) + @VisibleForTesting + suspend fun clearDataStore() { + applicationContext.dataStore.edit { it.clear() } + } + companion object { const val DATASTORE_NAME = "TutorialScheduler" - const val IS_LAUNCHED_SUFFIX = "_IS_LAUNCHED" - const val CONNECT_TIME_SUFFIX = "_CONNECTED_TIME" + const val LAUNCH_TIME_SUFFIX = "_LAUNCH_TIME" + const val CONNECT_TIME_SUFFIX = "_CONNECT_TIME" } } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt new file mode 100644 index 000000000000..3f1f68ad2897 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.tutorial.domain.interactor + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyboard.data.repository.KeyboardRepository +import com.android.systemui.touchpad.data.repository.TouchpadRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine + +@SysUISingleton +class KeyboardTouchpadConnectionInteractor +@Inject +constructor( + keyboardRepository: KeyboardRepository, + touchpadRepository: TouchpadRepository, +) { + + val connectionState: Flow<ConnectionState> = + combine( + keyboardRepository.isAnyKeyboardConnected, + touchpadRepository.isAnyTouchpadConnected + ) { keyboardConnected, touchpadConnected -> + ConnectionState(keyboardConnected, touchpadConnected) + } +} + +data class ConnectionState(val keyboardConnected: Boolean, val touchpadConnected: Boolean) diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt index b3b8f21a4a4b..a8d7dad42a93 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt @@ -26,9 +26,11 @@ import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUC import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository import com.android.systemui.keyboard.data.repository.KeyboardRepository import com.android.systemui.touchpad.data.repository.TouchpadRepository +import java.time.Duration import java.time.Instant import javax.inject.Inject import kotlin.time.Duration.Companion.hours +import kotlin.time.toKotlinDuration import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.filter @@ -84,9 +86,9 @@ constructor( private suspend fun schedule(deviceType: DeviceType) { if (!repo.wasEverConnected(deviceType)) { waitForDeviceConnection(deviceType) - repo.updateConnectTime(deviceType, Instant.now().toEpochMilli()) + repo.updateFirstConnectionTime(deviceType, Instant.now()) } - delay(remainingTimeMillis(start = repo.connectTime(deviceType))) + delay(remainingTime(start = repo.firstConnectionTime(deviceType)!!)) waitForDeviceConnection(deviceType) } @@ -95,9 +97,9 @@ constructor( private suspend fun launchTutorial(tutorialType: TutorialType) { if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH) - repo.updateLaunch(KEYBOARD) + repo.updateLaunchTime(KEYBOARD, Instant.now()) if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH) - repo.updateLaunch(TOUCHPAD) + repo.updateLaunchTime(TOUCHPAD, Instant.now()) // TODO: launch tutorial Log.d(TAG, "Launch tutorial for $tutorialType") } @@ -113,19 +115,21 @@ constructor( return if (deviceType == KEYBOARD) TutorialType.KEYBOARD else TutorialType.TOUCHPAD } - private fun remainingTimeMillis(start: Long): Long { - val elapsed = Instant.now().toEpochMilli() - start - return LAUNCH_DELAY - elapsed + private fun remainingTime(start: Instant): kotlin.time.Duration { + val elapsed = Duration.between(start, Instant.now()) + return LAUNCH_DELAY.minus(elapsed).toKotlinDuration() } companion object { const val TAG = "TutorialSchedulerInteractor" - private val DEFAULT_LAUNCH_DELAY = 72.hours.inWholeMilliseconds - private val LAUNCH_DELAY: Long + private val DEFAULT_LAUNCH_DELAY_SEC = 72.hours.inWholeSeconds + private val LAUNCH_DELAY: Duration get() = - SystemProperties.getLong( - "persist.peripheral_tutorial_delay_ms", - DEFAULT_LAUNCH_DELAY + Duration.ofSeconds( + SystemProperties.getLong( + "persist.peripheral_tutorial_delay_sec", + DEFAULT_LAUNCH_DELAY_SEC + ) ) } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionKeyTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt index c5b0ca78d65a..c5b0ca78d65a 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionKeyTutorialScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionTutorialContent.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt index c50b7dc06265..c50b7dc06265 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionTutorialContent.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialComponents.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt index 01ad585019d2..01ad585019d2 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialComponents.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialScreenConfig.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt index 0406bb9e6fef..0406bb9e6fef 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialScreenConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt new file mode 100644 index 000000000000..34ecc9518e83 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.tutorial.ui.view + +import android.os.Bundle +import android.view.WindowManager +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.lifecycle.Lifecycle.State.STARTED +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.lifecycleScope +import com.android.compose.theme.PlatformTheme +import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider +import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel.Factory.ViewModelFactoryAssistedProvider +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE +import java.util.Optional +import javax.inject.Inject +import kotlinx.coroutines.launch + +/** + * Activity for out of the box experience for keyboard and touchpad. Note that it's possible that + * either of them are actually not connected when this is launched + */ +class KeyboardTouchpadTutorialActivity +@Inject +constructor( + private val viewModelFactoryAssistedProvider: ViewModelFactoryAssistedProvider, + private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>, +) : ComponentActivity() { + + companion object { + const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type" + const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad" + const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard" + } + + private val vm by + viewModels<KeyboardTouchpadTutorialViewModel>( + factoryProducer = { + viewModelFactoryAssistedProvider.create(touchpadTutorialScreensProvider.isPresent) + } + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + // required to handle 3+ fingers on touchpad + window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) + lifecycle.addObserver(vm) + lifecycleScope.launch { + vm.closeActivity.collect { finish -> + if (finish) { + finish() + } + } + } + setContent { + PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) } + } + } +} + +@Composable +fun KeyboardTouchpadTutorialContainer( + vm: KeyboardTouchpadTutorialViewModel, + touchpadScreens: Optional<TouchpadTutorialScreensProvider>, +) { + val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED) + when (activeScreen) { + BACK_GESTURE -> + touchpadScreens + .get() + .BackGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack) + HOME_GESTURE -> + touchpadScreens + .get() + .HomeGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack) + ACTION_KEY -> + ActionKeyTutorialScreen( + onDoneButtonClicked = vm::onDoneButtonClicked, + onBack = vm::onBack + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt new file mode 100644 index 000000000000..315c102e94d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.tutorial.ui.viewmodel + +import androidx.lifecycle.AbstractSavedStateViewModelFactory +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState +import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE +import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import java.util.Optional +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterNot +import kotlinx.coroutines.flow.runningFold +import kotlinx.coroutines.launch + +class KeyboardTouchpadTutorialViewModel( + private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, + private val keyboardTouchpadConnectionInteractor: KeyboardTouchpadConnectionInteractor, + private val hasTouchpadTutorialScreens: Boolean, + handle: SavedStateHandle +) : ViewModel(), DefaultLifecycleObserver { + + private fun startingScreen(handle: SavedStateHandle): Screen { + val tutorialType: String? = handle[INTENT_TUTORIAL_TYPE_KEY] + return if (tutorialType == INTENT_TUTORIAL_TYPE_KEYBOARD) ACTION_KEY else BACK_GESTURE + } + + private val _screen = MutableStateFlow(startingScreen(handle)) + val screen: Flow<Screen> = _screen.filter { it.canBeShown() } + + private val _closeActivity: MutableStateFlow<Boolean> = MutableStateFlow(false) + val closeActivity: StateFlow<Boolean> = _closeActivity + + private val screensBackStack = ArrayDeque(listOf(_screen.value)) + + private var connectionState: ConnectionState = + ConnectionState(keyboardConnected = false, touchpadConnected = false) + + init { + viewModelScope.launch { + keyboardTouchpadConnectionInteractor.connectionState.collect { connectionState = it } + } + + viewModelScope.launch { + screen + .runningFold<Screen, Pair<Screen?, Screen?>>(null to null) { + previousScreensPair, + currentScreen -> + previousScreensPair.second to currentScreen + } + .collect { (previousScreen, currentScreen) -> + // ignore first empty emission + if (currentScreen != null) { + setupDeviceState(previousScreen, currentScreen) + } + } + } + + viewModelScope.launch { + // close activity if screen requires touchpad but we don't have it. This can only happen + // when current sysui build doesn't contain touchpad module dependency + _screen.filterNot { it.canBeShown() }.collect { _closeActivity.value = true } + } + } + + override fun onCleared() { + // this shouldn't be needed as onTutorialInvisible should already clear device state but + // it'd be really bad if we'd block gestures/shortcuts after leaving tutorial so just to be + // extra sure... + clearDeviceStateForScreen(_screen.value) + } + + override fun onStart(owner: LifecycleOwner) { + setupDeviceState(previousScreen = null, currentScreen = _screen.value) + } + + override fun onStop(owner: LifecycleOwner) { + clearDeviceStateForScreen(_screen.value) + } + + fun onDoneButtonClicked() { + var nextScreen = _screen.value.next() + while (nextScreen != null) { + if (requiredHardwarePresent(nextScreen)) { + break + } + nextScreen = nextScreen.next() + } + if (nextScreen == null) { + _closeActivity.value = true + } else { + _screen.value = nextScreen + screensBackStack.add(nextScreen) + } + } + + private fun Screen.canBeShown() = requiredHardware != TOUCHPAD || hasTouchpadTutorialScreens + + private fun setupDeviceState(previousScreen: Screen?, currentScreen: Screen) { + if (previousScreen?.requiredHardware == currentScreen.requiredHardware) return + previousScreen?.let { clearDeviceStateForScreen(it) } + when (currentScreen.requiredHardware) { + TOUCHPAD -> gesturesInteractor.get().disableGestures() + KEYBOARD -> {} // TODO(b/358587037) disabled keyboard shortcuts + } + } + + private fun clearDeviceStateForScreen(screen: Screen) { + when (screen.requiredHardware) { + TOUCHPAD -> gesturesInteractor.get().enableGestures() + KEYBOARD -> {} // TODO(b/358587037) enable keyboard shortcuts + } + } + + private fun requiredHardwarePresent(screen: Screen): Boolean = + when (screen.requiredHardware) { + KEYBOARD -> connectionState.keyboardConnected + TOUCHPAD -> connectionState.touchpadConnected + } + + fun onBack() { + if (screensBackStack.size <= 1) { + _closeActivity.value = true + } else { + screensBackStack.removeLast() + _screen.value = screensBackStack.last() + } + } + + class Factory + @AssistedInject + constructor( + private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, + private val keyboardTouchpadConnected: KeyboardTouchpadConnectionInteractor, + @Assisted private val hasTouchpadTutorialScreens: Boolean, + ) : AbstractSavedStateViewModelFactory() { + + @AssistedFactory + fun interface ViewModelFactoryAssistedProvider { + fun create(@Assisted hasTouchpadTutorialScreens: Boolean): Factory + } + + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create( + key: String, + modelClass: Class<T>, + handle: SavedStateHandle + ): T = + KeyboardTouchpadTutorialViewModel( + gesturesInteractor, + keyboardTouchpadConnected, + hasTouchpadTutorialScreens, + handle + ) + as T + } +} + +enum class RequiredHardware { + TOUCHPAD, + KEYBOARD +} + +enum class Screen(val requiredHardware: RequiredHardware) { + BACK_GESTURE(requiredHardware = TOUCHPAD), + HOME_GESTURE(requiredHardware = TOUCHPAD), + ACTION_KEY(requiredHardware = KEYBOARD); + + fun next(): Screen? = + when (this) { + BACK_GESTURE -> HOME_GESTURE + HOME_GESTURE -> ACTION_KEY + ACTION_KEY -> null + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index 81b0064f0f03..49303e089036 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -91,11 +91,11 @@ interface KeyguardRepository { * the z-order (which is not really above the system UI window, but rather - the lock-screen * becomes invisible to reveal the "occluding activity"). */ - val isKeyguardShowing: Flow<Boolean> + val isKeyguardShowing: StateFlow<Boolean> /** Is an activity showing over the keyguard? */ @Deprecated("Use KeyguardTransitionInteractor + KeyguardState.OCCLUDED") - val isKeyguardOccluded: Flow<Boolean> + val isKeyguardOccluded: StateFlow<Boolean> /** * Whether the device is locked or unlocked right now. This is true when keyguard has been diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt index ae830eed2c6b..1042ae32fea0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -30,7 +30,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt index 2a8bb471c217..6e04133dcb4a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt @@ -36,8 +36,6 @@ import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce @SysUISingleton @@ -73,15 +71,11 @@ constructor( listenForTransitionToCamera(scope, keyguardInteractor) } - private val canDismissLockscreen: Flow<Boolean> = - combine( - keyguardInteractor.isKeyguardShowing, - keyguardInteractor.isKeyguardDismissible, - keyguardInteractor.biometricUnlockState, - ) { isKeyguardShowing, isKeyguardDismissible, biometricUnlockState -> - (isWakeAndUnlock(biometricUnlockState.mode) || - (!isKeyguardShowing && isKeyguardDismissible)) - } + private fun canDismissLockscreen(): Boolean { + return isWakeAndUnlock(keyguardInteractor.biometricUnlockState.value.mode) || + (!keyguardInteractor.isKeyguardShowing.value && + keyguardInteractor.isKeyguardDismissible.value) + } /** * Listen for the signal that we're waking up and figure what state we need to transition to. @@ -96,22 +90,18 @@ constructor( .debounce(50L) .sample( startedKeyguardTransitionStep, - keyguardInteractor.biometricUnlockState, - keyguardInteractor.primaryBouncerShowing, - keyguardInteractor.isKeyguardOccluded, - canDismissLockscreen, wakeToGoneInteractor.canWakeDirectlyToGone, ) .collect { ( _, startedStep, - biometricUnlockState, - primaryBouncerShowing, - isKeyguardOccludedLegacy, - canDismissLockscreen, canWakeDirectlyToGone, ) -> + val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value + val biometricUnlockMode = keyguardInteractor.biometricUnlockState.value.mode + val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value + if (!maybeHandleInsecurePowerGesture()) { val shouldTransitionToLockscreen = if (KeyguardWmStateRefactor.isEnabled) { @@ -121,12 +111,10 @@ constructor( // completes. !maybeStartTransitionToOccludedOrInsecureCamera { state, reason -> startTransitionTo(state, ownerReason = reason) - } && - !isWakeAndUnlock(biometricUnlockState.mode) && - !primaryBouncerShowing + } && !isWakeAndUnlock(biometricUnlockMode) && !primaryBouncerShowing } else { !isKeyguardOccludedLegacy && - !isWakeAndUnlock(biometricUnlockState.mode) && + !isWakeAndUnlock(biometricUnlockMode) && !primaryBouncerShowing } @@ -136,11 +124,11 @@ constructor( !KeyguardWmStateRefactor.isEnabled && isKeyguardOccludedLegacy val shouldTransitionToGone = - (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) || + (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen()) || (KeyguardWmStateRefactor.isEnabled && canWakeDirectlyToGone) if (shouldTransitionToGone) { - // TODO(b/336576536): Check if adaptation for scene framework is needed + // TODO(b/360368320): Adapt for scene framework if (SceneContainerFlag.isEnabled) return@collect startTransitionTo( toState = KeyguardState.GONE, @@ -198,7 +186,6 @@ constructor( * PRIMARY_BOUNCER. */ private fun listenForAodToPrimaryBouncer() { - // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return scope.launch("$TAG#listenForAodToPrimaryBouncer") { keyguardInteractor.primaryBouncerShowing diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index 61446c19605c..49e4c707af18 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -42,8 +42,6 @@ import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.launch @@ -83,13 +81,10 @@ constructor( listenForTransitionToCamera(scope, keyguardInteractor) } - private val canTransitionToGoneOnWake: Flow<Boolean> = - combine( - keyguardInteractor.isKeyguardShowing, - keyguardInteractor.isKeyguardDismissible, - ) { isKeyguardShowing, isKeyguardDismissible -> - isKeyguardDismissible && !isKeyguardShowing - } + private fun canDismissLockscreen(): Boolean { + return !keyguardInteractor.isKeyguardShowing.value && + keyguardInteractor.isKeyguardDismissible.value + } private fun listenForDozingToGoneViaBiometrics() { if (KeyguardWmStateRefactor.isEnabled) { @@ -112,7 +107,7 @@ constructor( ) -> if (isWakeAndUnlock(biometricUnlockState.mode)) { if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed + // TODO(b/360368320): Adapt for scene framework } else { startTransitionTo( KeyguardState.GONE, @@ -135,44 +130,29 @@ constructor( .debounce(50L) .filterRelevantKeyguardStateAnd { isAwake -> isAwake } .sample( - keyguardInteractor.isKeyguardOccluded, communalInteractor.isCommunalAvailable, communalSceneInteractor.isIdleOnCommunal, - canTransitionToGoneOnWake, - keyguardInteractor.primaryBouncerShowing, ) - .collect { - ( - _, - occluded, - isCommunalAvailable, - isIdleOnCommunal, - canTransitionToGoneOnWake, - primaryBouncerShowing) -> + .collect { (_, isCommunalAvailable, isIdleOnCommunal) -> + val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value + val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value + if (!deviceEntryInteractor.isLockscreenEnabled()) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo(KeyguardState.GONE) } - } else if (canTransitionToGoneOnWake) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed - } else { + } else if (canDismissLockscreen()) { + if (!SceneContainerFlag.isEnabled) { startTransitionTo(KeyguardState.GONE) } } else if (primaryBouncerShowing) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo(KeyguardState.PRIMARY_BOUNCER) } - } else if (occluded) { + } else if (isKeyguardOccludedLegacy) { startTransitionTo(KeyguardState.OCCLUDED) } else if (isIdleOnCommunal && !communalSceneKtfRefactor()) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } } else if ( @@ -183,9 +163,7 @@ constructor( ) { // This case handles tapping the power button to transition through // dream -> off -> hub. - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is needed - } else { + if (!SceneContainerFlag.isEnabled) { transitionToGlanceableHub() } } else { @@ -228,30 +206,21 @@ constructor( !isWakeAndUnlock(biometricUnlockState.mode) ) { if (canWakeDirectlyToGone) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is - // needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.GONE, ownerReason = "waking from dozing" ) } } else if (primaryBouncerShowing) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is - // needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.PRIMARY_BOUNCER, ownerReason = "waking from dozing" ) } } else if (isIdleOnCommunal && !communalSceneKtfRefactor()) { - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is - // needed - } else { + if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.GLANCEABLE_HUB, ownerReason = "waking from dozing" @@ -265,10 +234,7 @@ constructor( ) { // This case handles tapping the power button to transition through // dream -> off -> hub. - if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Check if adaptation for scene framework is - // needed - } else { + if (!SceneContainerFlag.isEnabled) { transitionToGlanceableHub() } } else { @@ -285,9 +251,10 @@ constructor( private suspend fun transitionToGlanceableHub() { if (communalSceneKtfRefactor()) { communalSceneInteractor.changeScene( - CommunalScenes.Communal, + newScene = CommunalScenes.Communal, + loggingReason = "from dozing to hub", // Immediately show the hub when transitioning from dozing to hub. - CommunalTransitionKeys.Immediately, + transitionKey = CommunalTransitionKeys.Immediately, ) } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index 17c1e823a1ca..4666430398ec 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -20,7 +20,9 @@ import android.animation.ValueAnimator import com.android.app.animation.Interpolators import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.communalSceneKtfRefactor +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor +import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -32,7 +34,6 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag -import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds @@ -59,6 +60,7 @@ constructor( @Main mainDispatcher: CoroutineDispatcher, keyguardInteractor: KeyguardInteractor, private val glanceableHubTransitions: GlanceableHubTransitions, + private val communalSceneInteractor: CommunalSceneInteractor, private val communalSettingsInteractor: CommunalSettingsInteractor, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, @@ -127,17 +129,24 @@ constructor( } } - fun startToLockscreenTransition() { + fun startToLockscreenOrGlanceableHubTransition(openHub: Boolean) { scope.launch { if ( transitionInteractor.startedKeyguardState.replayCache.last() == KeyguardState.DREAMING ) { if (powerInteractor.detailedWakefulness.value.isAwake()) { - startTransitionTo( - KeyguardState.LOCKSCREEN, - ownerReason = "Dream has ended and device is awake" - ) + if (openHub) { + communalSceneInteractor.changeScene( + newScene = CommunalScenes.Communal, + loggingReason = "FromDreamingTransitionInteractor", + ) + } else { + startTransitionTo( + KeyguardState.LOCKSCREEN, + ownerReason = "Dream has ended and device is awake" + ) + } } } } @@ -208,15 +217,15 @@ constructor( scope.launch { keyguardInteractor.isAbleToDream - .sampleCombine( - keyguardInteractor.isKeyguardShowing, - keyguardInteractor.isKeyguardDismissible, - ) - .filterRelevantKeyguardStateAnd { - (isDreaming, isKeyguardShowing, isKeyguardDismissible) -> - !isDreaming && isKeyguardDismissible && !isKeyguardShowing + .filterRelevantKeyguardStateAnd { isDreaming -> !isDreaming } + .collect { + if ( + keyguardInteractor.isKeyguardDismissible.value && + !keyguardInteractor.isKeyguardShowing.value + ) { + startTransitionTo(KeyguardState.GONE) + } } - .collect { startTransitionTo(KeyguardState.GONE) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index befcc9e6c8ee..0aa50e04087e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -159,6 +159,7 @@ constructor( if (communalSceneKtfRefactor()) { communalSceneInteractor.changeScene( newScene = CommunalScenes.Blank, + loggingReason = "hub to dozing", transitionKey = CommunalTransitionKeys.Immediately, keyguardState = KeyguardState.DOZING, ) @@ -182,6 +183,7 @@ constructor( if (communalSceneKtfRefactor()) { communalSceneInteractor.changeScene( newScene = CommunalScenes.Blank, + loggingReason = "hub to occluded (KeyguardWmStateRefactor)", transitionKey = CommunalTransitionKeys.SimpleFade, keyguardState = state, ) @@ -211,6 +213,7 @@ constructor( .collect { _ -> communalSceneInteractor.changeScene( newScene = CommunalScenes.Blank, + loggingReason = "hub to occluded", transitionKey = CommunalTransitionKeys.SimpleFade, keyguardState = KeyguardState.OCCLUDED, ) @@ -228,7 +231,6 @@ constructor( } private fun listenForHubToGone() { - // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return if (communalSceneKtfRefactor()) { scope.launch { @@ -254,6 +256,7 @@ constructor( } else { communalSceneInteractor.changeScene( newScene = CommunalScenes.Blank, + loggingReason = "hub to gone", transitionKey = CommunalTransitionKeys.SimpleFade, keyguardState = KeyguardState.GONE ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index 5dc020f41ad3..cd3df07eea55 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -276,7 +276,6 @@ constructor( } private fun listenForLockscreenToGone() { - // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return if (KeyguardWmStateRefactor.isEnabled) return scope.launch("$TAG#listenForLockscreenToGone") { @@ -292,7 +291,6 @@ constructor( } private fun listenForLockscreenToGoneDragging() { - // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return if (KeyguardWmStateRefactor.isEnabled) { // When the refactor is enabled, we no longer use isKeyguardGoingAway. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index 905ca8eda87f..0343786bb1fb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -76,7 +76,6 @@ constructor( } private fun listenForOccludedToPrimaryBouncer() { - // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return scope.launch { keyguardInteractor.primaryBouncerShowing @@ -146,8 +145,9 @@ constructor( if (SceneContainerFlag.isEnabled) return if (communalSceneKtfRefactor()) { communalSceneInteractor.changeScene( - CommunalScenes.Communal, - CommunalTransitionKeys.SimpleFade + newScene = CommunalScenes.Communal, + loggingReason = "occluded to hub", + transitionKey = CommunalTransitionKeys.SimpleFade ) } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index 2823b93b4847..52323a51b011 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -35,7 +35,7 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.kotlin.sample -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher @@ -175,7 +175,10 @@ constructor( !communalSceneInteractor.isLaunchingWidget.value && communalSceneInteractor.editModeState.value == null ) { - communalSceneInteractor.snapToScene(CommunalScenes.Blank) + communalSceneInteractor.snapToScene( + newScene = CommunalScenes.Blank, + loggingReason = "FromPrimaryBouncerTransitionInteractor", + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 0df989e9353f..4cab2bb5dba8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -216,14 +216,14 @@ constructor( /** Whether the keyguard is showing or not. */ @Deprecated("Use KeyguardTransitionInteractor + KeyguardState") - val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing + val isKeyguardShowing: StateFlow<Boolean> = repository.isKeyguardShowing /** Whether the keyguard is dismissible or not. */ val isKeyguardDismissible: StateFlow<Boolean> = repository.isKeyguardDismissible /** Whether the keyguard is occluded (covered by an activity). */ @Deprecated("Use KeyguardTransitionInteractor + KeyguardState.OCCLUDED") - val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded + val isKeyguardOccluded: StateFlow<Boolean> = repository.isKeyguardOccluded /** Whether the keyguard is going away. */ @Deprecated("Use KeyguardTransitionInteractor + KeyguardState.GONE") @@ -253,7 +253,7 @@ constructor( val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow() /** Whether the primary bouncer is showing or not. */ - @JvmField val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow + @JvmField val primaryBouncerShowing: StateFlow<Boolean> = bouncerRepository.primaryBouncerShow /** Whether the alternate bouncer is showing or not. */ val alternateBouncerShowing: Flow<Boolean> = @@ -274,7 +274,7 @@ constructor( val statusBarState: Flow<StatusBarState> = repository.statusBarState /** Observable for [BiometricUnlockModel] when biometrics are used to unlock the device. */ - val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState + val biometricUnlockState: StateFlow<BiometricUnlockModel> = repository.biometricUnlockState /** Keyguard is present and is not occluded. */ val isKeyguardVisible: Flow<Boolean> = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt index 2ebd9e8c5f2b..b2183007c48c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt @@ -71,7 +71,7 @@ constructor( ) } else { if (SceneContainerFlag.isEnabled) { - // TODO(b/336576536): Some part of the transition implemented for flag off is + // TODO(b/360372242): Some part of the transition implemented for flag off is // missing here. There are two things achieved with this: // 1. Keyguard is hidden when the setup wizard is shown. This part is already // implemented in scene container by disabling visibility instead of going diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index 15e6b1d78ea0..28a17ef4922a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -92,9 +92,9 @@ constructor( val button = view as ImageView val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) val disposableHandle = - view.repeatWhenAttached(mainImmediateDispatcher) { - repeatOnLifecycle(Lifecycle.State.STARTED) { - launch("$TAG#viewModel") { + view.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { viewModel.collect { buttonModel -> updateButton( view = button, @@ -104,7 +104,7 @@ constructor( } } - launch("$TAG#updateButtonAlpha") { + launch { updateButtonAlpha( view = button, viewModel = viewModel, @@ -112,7 +112,7 @@ constructor( ) } - launch("$TAG#configurationBasedDimensions") { + launch { configurationBasedDimensions.collect { dimensions -> button.updateLayoutParams<ViewGroup.LayoutParams> { width = dimensions.buttonSizePx.width diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index aab5b9b29680..89851dbec7bc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -152,6 +152,62 @@ object KeyguardRootViewBinder { } } } + + if ( + KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled + ) { + launch("$TAG#alpha") { + viewModel.alpha(viewState).collect { alpha -> + view.alpha = alpha + if (KeyguardBottomAreaRefactor.isEnabled) { + childViews[statusViewId]?.alpha = alpha + childViews[burnInLayerId]?.alpha = alpha + } + } + } + } + + if (MigrateClocksToBlueprint.isEnabled) { + launch("$TAG#translationY") { + // When translation happens in burnInLayer, it won't be weather clock + // large clock isn't added to burnInLayer due to its scale transition + // so we also need to add translation to it here + // same as translationX + viewModel.translationY.collect { y -> + childViews[burnInLayerId]?.translationY = y + childViews[largeClockId]?.translationY = y + childViews[aodNotificationIconContainerId]?.translationY = y + } + } + + launch("$TAG#translationX") { + viewModel.translationX.collect { state -> + val px = state.value ?: return@collect + when { + state.isToOrFrom(KeyguardState.AOD) -> { + // Large Clock is not translated in the x direction + childViews[burnInLayerId]?.translationX = px + childViews[aodNotificationIconContainerId]?.translationX = + px + } + state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> { + for ((key, childView) in childViews.entries) { + when (key) { + indicationArea, + startButton, + endButton, + lockIcon, + deviceEntryIcon -> { + // Do not move these views + } + else -> childView.translationX = px + } + } + } + } + } + } + } } } disposables += @@ -188,20 +244,6 @@ object KeyguardRootViewBinder { } } - if ( - KeyguardBottomAreaRefactor.isEnabled || DeviceEntryUdfpsRefactor.isEnabled - ) { - launch { - viewModel.alpha(viewState).collect { alpha -> - view.alpha = alpha - if (KeyguardBottomAreaRefactor.isEnabled) { - childViews[statusViewId]?.alpha = alpha - childViews[burnInLayerId]?.alpha = alpha - } - } - } - } - if (MigrateClocksToBlueprint.isEnabled) { launch { viewModel.burnInLayerVisibility.collect { visibility -> @@ -222,46 +264,6 @@ object KeyguardRootViewBinder { } launch { - // When translation happens in burnInLayer, it won't be weather clock - // large clock isn't added to burnInLayer due to its scale transition - // so we also need to add translation to it here - // same as translationX - viewModel.translationY.collect { y -> - childViews[burnInLayerId]?.translationY = y - childViews[largeClockId]?.translationY = y - childViews[aodNotificationIconContainerId]?.translationY = y - } - } - - launch { - viewModel.translationX.collect { state -> - val px = state.value ?: return@collect - when { - state.isToOrFrom(KeyguardState.AOD) -> { - // Large Clock is not translated in the x direction - childViews[burnInLayerId]?.translationX = px - childViews[aodNotificationIconContainerId]?.translationX = - px - } - state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> { - for ((key, childView) in childViews.entries) { - when (key) { - indicationArea, - startButton, - endButton, - lockIcon, - deviceEntryIcon -> { - // Do not move these views - } - else -> childView.translationX = px - } - } - } - } - } - } - - launch { viewModel.scale.collect { scaleViewModel -> if (scaleViewModel.scaleClockOnly) { // For clocks except weather clock, we have scale transition diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplier.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplier.kt index fb6efd3310f6..3b36762f19da 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplier.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplier.kt @@ -34,7 +34,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.TAG import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import java.util.concurrent.Executor import javax.inject.Inject diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt index 34c1436c3235..38f5d3e76c7c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt @@ -50,5 +50,9 @@ constructor( } .distinctUntilChanged() - fun openCommunalHub() = communalInteractor.changeScene(CommunalScenes.Communal) + fun openCommunalHub() = + communalInteractor.changeScene( + newScene = CommunalScenes.Communal, + loggingReason = "accessibility", + ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt index b5ec7a6511f1..10605b28a862 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt @@ -18,7 +18,6 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.app.animation.Interpolators.EMPHASIZED import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING @@ -39,10 +38,8 @@ import kotlinx.coroutines.flow.Flow class DreamingToLockscreenTransitionViewModel @Inject constructor( - private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor, animationFlow: KeyguardTransitionAnimationFlow, ) : DeviceEntryIconTransition { - fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition() private val transitionAnimation = animationFlow.setup( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index 050ef6f94f0a..06f77bfe54c6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -270,7 +270,7 @@ constructor( occludedToLockscreenTransitionViewModel.lockscreenAlpha, primaryBouncerToAodTransitionViewModel.lockscreenAlpha, primaryBouncerToGoneTransitionViewModel.lockscreenAlpha, - primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha, + primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState), ) .onStart { emit(1f) } ) { hideKeyguard, alpha -> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt index 59cb6e5cef91..666c9f8e243b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt @@ -32,6 +32,7 @@ import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -72,7 +73,7 @@ constructor( /** Whether the content of the scene UI should be shown. */ val isContentVisible: StateFlow<Boolean> = _isContentVisible.asStateFlow() - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { coroutineScope { launch { combine( @@ -92,6 +93,8 @@ constructor( .map { !it } .collectLatest { _isContentVisible.value = it } } + + awaitCancellation() } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt index 7511101bf04e..d29f5129bd59 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.util.MathUtils import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor @@ -58,7 +59,14 @@ constructor( onStep = { it } ) - val lockscreenAlpha: Flow<Float> = shortcutsAlpha + fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> { + var currentAlpha = 0f + return transitionAnimation.sharedFlow( + duration = 250.milliseconds, + onStart = { currentAlpha = viewState.alpha() }, + onStep = { MathUtils.lerp(currentAlpha, 1f, it) }, + ) + } val deviceEntryBackgroundViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f) diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt index ebb0ea62a10c..bd3d40b114e3 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt @@ -57,7 +57,7 @@ interface Activatable { * } * ``` */ - suspend fun activate() + suspend fun activate(): Nothing } /** diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt index f080a421d295..4dd76f8c78cb 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt @@ -34,7 +34,7 @@ abstract class SafeActivatable : Activatable { _isActive.set(value) } - final override suspend fun activate() { + final override suspend fun activate(): Nothing { val allowed = _isActive.compareAndSet(false, true) check(allowed) { "Cannot activate an already active activatable!" } @@ -57,7 +57,7 @@ abstract class SafeActivatable : Activatable { * * Implementations could follow this pattern: * ```kotlin - * override suspend fun onActivated() { + * override suspend fun onActivated(): Nothing { * coroutineScope { * launch { ... } * launch { ... } @@ -68,5 +68,5 @@ abstract class SafeActivatable : Activatable { * * @see activate */ - protected abstract suspend fun onActivated() + protected abstract suspend fun onActivated(): Nothing } diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt index 77314813c34a..2edde4ad046f 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt @@ -19,12 +19,15 @@ package com.android.systemui.lifecycle import android.view.View import androidx.compose.runtime.Composable import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.launch /** Base class for all System UI view-models. */ abstract class SysUiViewModel : SafeActivatable() { - override suspend fun onActivated() = Unit + override suspend fun onActivated(): Nothing { + awaitCancellation() + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt index 62759a4843d9..3c25e6205b05 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt @@ -54,7 +54,6 @@ import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel.Co import com.android.systemui.media.controls.ui.viewmodel.MediaOutputSwitcherViewModel import com.android.systemui.media.controls.ui.viewmodel.MediaPlayerViewModel import com.android.systemui.media.controls.util.MediaDataUtils -import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.monet.ColorScheme import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R @@ -76,7 +75,6 @@ object MediaControlViewBinder { falsingManager: FalsingManager, @Background backgroundDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, - mediaFlags: MediaFlags, ) { val mediaCard = viewHolder.player mediaCard.repeatWhenAttached { @@ -91,7 +89,6 @@ object MediaControlViewBinder { falsingManager, backgroundDispatcher, mainDispatcher, - mediaFlags ) } } @@ -107,7 +104,6 @@ object MediaControlViewBinder { falsingManager: FalsingManager, backgroundDispatcher: CoroutineDispatcher, mainDispatcher: CoroutineDispatcher, - mediaFlags: MediaFlags, ) { // Set up media control location and its listener. viewModel.onLocationChanged(viewController.currentEndLocation) @@ -164,18 +160,6 @@ object MediaControlViewBinder { isSongUpdated ) - // TODO: We don't need to refresh this state constantly, only if the - // state actually changed to something which might impact the - // measurement. State refresh interferes with the translation - // animation, only run it if it's not running. - if (!viewController.metadataAnimationHandler.isRunning) { - // Don't refresh in scene framework, because it will calculate - // with invalid layout sizes - if (!mediaFlags.isSceneContainerEnabled()) { - viewController.refreshState() - } - } - if (viewModel.playTurbulenceNoise) { viewController.setUpTurbulenceNoise() } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index 62a72184190d..fb2bbde37a18 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -223,7 +223,7 @@ constructor( if (!mediaFlags.isSceneContainerEnabled()) { MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() } } else { - controllerByViewModel.values.forEach { it.updateAnimatorDurationScale() } + controllerById.values.forEach { it.updateAnimatorDurationScale() } } } } @@ -324,7 +324,7 @@ constructor( private var widthInSceneContainerPx = 0 private var heightInSceneContainerPx = 0 - private val controllerByViewModel = mutableMapOf<MediaCommonViewModel, MediaViewController>() + private val controllerById = mutableMapOf<String, MediaViewController>() private val commonViewModels = mutableListOf<MediaCommonViewModel>() init { @@ -738,7 +738,7 @@ constructor( viewController.heightInSceneContainerPx = heightInSceneContainerPx } viewController.attachPlayer(viewHolder) - viewController.mediaViewHolder.player.layoutParams = lp + viewController.mediaViewHolder?.player?.layoutParams = lp MediaControlViewBinder.bind( viewHolder, commonViewModel.controlViewModel, @@ -746,15 +746,15 @@ constructor( falsingManager, backgroundDispatcher, mainDispatcher, - mediaFlags ) mediaContent.addView(viewHolder.player, position) + controllerById[commonViewModel.instanceId.toString()] = viewController } is MediaCommonViewModel.MediaRecommendations -> { val viewHolder = RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent) viewController.attachRecommendations(viewHolder) - viewController.recommendationViewHolder.recommendations.layoutParams = lp + viewController.recommendationViewHolder?.recommendations?.layoutParams = lp MediaRecommendationsViewBinder.bind( viewHolder, commonViewModel.recsViewModel, @@ -762,11 +762,11 @@ constructor( falsingManager, ) mediaContent.addView(viewHolder.recommendations, position) + controllerById[commonViewModel.key] = viewController } } onAddOrUpdateVisibleToUserCard(position, isMediaCardUpdate = false) viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded) - controllerByViewModel[commonViewModel] = viewController updateViewControllerToState(viewController, noAnimation = true) updatePageIndicator() if ( @@ -793,14 +793,19 @@ constructor( } private fun onRemoved(commonViewModel: MediaCommonViewModel) { - controllerByViewModel.remove(commonViewModel)?.let { + val id = + when (commonViewModel) { + is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString() + is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key + } + controllerById.remove(id)?.let { when (commonViewModel) { is MediaCommonViewModel.MediaControl -> { - mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder.player) - mediaContent.removeView(it.mediaViewHolder.player) + mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder!!.player) + mediaContent.removeView(it.mediaViewHolder!!.player) } is MediaCommonViewModel.MediaRecommendations -> { - mediaContent.removeView(it.recommendationViewHolder.recommendations) + mediaContent.removeView(it.recommendationViewHolder!!.recommendations) } } it.onDestroy() @@ -811,14 +816,19 @@ constructor( } private fun onMoved(commonViewModel: MediaCommonViewModel, from: Int, to: Int) { - controllerByViewModel[commonViewModel]?.let { + val id = + when (commonViewModel) { + is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString() + is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key + } + controllerById[id]?.let { mediaContent.removeViewAt(from) when (commonViewModel) { is MediaCommonViewModel.MediaControl -> { - mediaContent.addView(it.mediaViewHolder.player, to) + mediaContent.addView(it.mediaViewHolder!!.player, to) } is MediaCommonViewModel.MediaRecommendations -> { - mediaContent.addView(it.recommendationViewHolder.recommendations, to) + mediaContent.addView(it.recommendationViewHolder!!.recommendations, to) } } } @@ -855,15 +865,16 @@ constructor( } } .toHashSet() - controllerByViewModel - .filter { - when (val viewModel = it.key) { - is MediaCommonViewModel.MediaControl -> - !viewIds.contains(viewModel.instanceId.toString()) - is MediaCommonViewModel.MediaRecommendations -> !viewIds.contains(viewModel.key) - } + controllerById + .filter { !viewIds.contains(it.key) } + .forEach { + mediaCarouselScrollHandler.onPrePlayerRemoved(it.value.mediaViewHolder?.player) + mediaContent.removeView(it.value.mediaViewHolder?.player) + mediaContent.removeView(it.value.recommendationViewHolder?.recommendations) + it.value.onDestroy() + mediaCarouselScrollHandler.onPlayersChanged() + updatePageIndicator() } - .forEach { onRemoved(it.key) } } private suspend fun getMediaLockScreenSetting(): Boolean { @@ -1176,12 +1187,12 @@ constructor( commonViewModels.forEach { viewModel -> when (viewModel) { is MediaCommonViewModel.MediaControl -> { - controllerByViewModel[viewModel]?.mediaViewHolder?.let { + controllerById[viewModel.instanceId.toString()]?.mediaViewHolder?.let { mediaContent.addView(it.player) } } is MediaCommonViewModel.MediaRecommendations -> { - controllerByViewModel[viewModel]?.recommendationViewHolder?.let { + controllerById[viewModel.key]?.recommendationViewHolder?.let { mediaContent.addView(it.recommendations) } } @@ -1234,9 +1245,7 @@ constructor( updateViewControllerToState(mediaPlayer.mediaViewController, immediately) } } else { - controllerByViewModel.values.forEach { - updateViewControllerToState(it, immediately) - } + controllerById.values.forEach { updateViewControllerToState(it, immediately) } } maybeResetSettingsCog() updatePageIndicatorAlpha() @@ -1296,9 +1305,7 @@ constructor( player.setListening(visibleToUser && currentlyExpanded) } } else { - controllerByViewModel.values.forEach { - it.setListening(visibleToUser && currentlyExpanded) - } + controllerById.values.forEach { it.setListening(visibleToUser && currentlyExpanded) } } } @@ -1316,7 +1323,7 @@ constructor( Math.max(height, controller.currentHeight + controller.translationY.toInt()) } } else { - controllerByViewModel.values.forEach { + controllerById.values.forEach { // When transitioning the view to gone, the view gets smaller, but the translation // Doesn't, let's add the translation width = Math.max(width, it.currentWidth + it.translationX.toInt()) @@ -1413,7 +1420,7 @@ constructor( mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation) } } else { - controllerByViewModel.values.forEach { controller -> + controllerById.values.forEach { controller -> if (animate) { controller.animatePendingStateChange(duration, startDelay) } @@ -1441,7 +1448,7 @@ constructor( if (!mediaFlags.isSceneContainerEnabled()) { MediaPlayerData.players().forEach { it.closeGuts(immediate) } } else { - controllerByViewModel.values.forEach { it.closeGuts(immediate) } + controllerById.values.forEach { it.closeGuts(immediate) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt index 681bf390e3e9..584908ff2aad 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt @@ -196,8 +196,8 @@ constructor( private var isNextButtonAvailable = false /** View holders for controller */ - lateinit var recommendationViewHolder: RecommendationViewHolder - lateinit var mediaViewHolder: MediaViewHolder + var recommendationViewHolder: RecommendationViewHolder? = null + var mediaViewHolder: MediaViewHolder? = null private lateinit var seekBarObserver: SeekBarObserver private lateinit var turbulenceNoiseController: TurbulenceNoiseController @@ -752,16 +752,18 @@ constructor( private fun updateDisplayForScrubbingChange() { mainExecutor.execute { val isTimeVisible = canShowScrubbingTime && isScrubbing - MediaControlViewBinder.setVisibleAndAlpha( - expandedLayout, - mediaViewHolder.scrubbingTotalTimeView.id, - isTimeVisible - ) - MediaControlViewBinder.setVisibleAndAlpha( - expandedLayout, - mediaViewHolder.scrubbingElapsedTimeView.id, - isTimeVisible - ) + mediaViewHolder!!.let { + MediaControlViewBinder.setVisibleAndAlpha( + expandedLayout, + it.scrubbingTotalTimeView.id, + isTimeVisible + ) + MediaControlViewBinder.setVisibleAndAlpha( + expandedLayout, + it.scrubbingElapsedTimeView.id, + isTimeVisible + ) + } MediaControlViewModel.SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach { id -> val isButtonVisible: Boolean @@ -780,14 +782,16 @@ constructor( notVisibleValue = ConstraintSet.GONE } } - MediaControlViewBinder.setSemanticButtonVisibleAndAlpha( - mediaViewHolder.getAction(id), - expandedLayout, - collapsedLayout, - isButtonVisible, - notVisibleValue, - showInCollapsed = true - ) + mediaViewHolder!!.let { + MediaControlViewBinder.setSemanticButtonVisibleAndAlpha( + it.getAction(id), + expandedLayout, + collapsedLayout, + isButtonVisible, + notVisibleValue, + showInCollapsed = true + ) + } } if (!metadataAnimationHandler.isRunning) { @@ -813,39 +817,41 @@ constructor( fun setUpTurbulenceNoise() { if (!mediaFlags.isSceneContainerEnabled()) return - if (!this::turbulenceNoiseAnimationConfig.isInitialized) { - turbulenceNoiseAnimationConfig = - createTurbulenceNoiseConfig( - mediaViewHolder.loadingEffectView, - mediaViewHolder.turbulenceNoiseView, - colorSchemeTransition - ) - } - if (Flags.shaderlibLoadingEffectRefactor()) { - if (!this::loadingEffect.isInitialized) { - loadingEffect = - LoadingEffect( - TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, - turbulenceNoiseAnimationConfig, - noiseDrawCallback, - stateChangedCallback + mediaViewHolder!!.let { + if (!this::turbulenceNoiseAnimationConfig.isInitialized) { + turbulenceNoiseAnimationConfig = + createTurbulenceNoiseConfig( + it.loadingEffectView, + it.turbulenceNoiseView, + colorSchemeTransition ) } - colorSchemeTransition.loadingEffect = loadingEffect - loadingEffect.play() - mainExecutor.executeDelayed( - loadingEffect::finish, - MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION - ) - } else { - turbulenceNoiseController.play( - TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, - turbulenceNoiseAnimationConfig - ) - mainExecutor.executeDelayed( - turbulenceNoiseController::finish, - MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION - ) + if (Flags.shaderlibLoadingEffectRefactor()) { + if (!this::loadingEffect.isInitialized) { + loadingEffect = + LoadingEffect( + TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, + turbulenceNoiseAnimationConfig, + noiseDrawCallback, + stateChangedCallback + ) + } + colorSchemeTransition.loadingEffect = loadingEffect + loadingEffect.play() + mainExecutor.executeDelayed( + loadingEffect::finish, + MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION + ) + } else { + turbulenceNoiseController.play( + TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, + turbulenceNoiseAnimationConfig + ) + mainExecutor.executeDelayed( + turbulenceNoiseController::finish, + MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION + ) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt index 2ce7044897be..dd1fa76c65c9 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt @@ -36,8 +36,8 @@ import com.android.systemui.mediaprojection.appselector.view.RecentTasksAdapter. import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener import com.android.systemui.res.R import com.android.systemui.util.recycler.HorizontalSpacerItemDecoration -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT +import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.splitscreen.SplitScreen import com.android.wm.shell.util.SplitBounds import java.util.Optional diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt deleted file mode 100644 index e4bafcd9fdb3..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt +++ /dev/null @@ -1,298 +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.systemui.qs - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.os.UserHandle -import android.provider.Settings -import android.text.TextUtils -import android.util.ArraySet -import android.util.Log -import androidx.annotation.GuardedBy -import androidx.annotation.VisibleForTesting -import com.android.systemui.Dumpable -import com.android.systemui.broadcast.BroadcastDispatcher -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.dump.DumpManager -import com.android.systemui.util.UserAwareController -import com.android.systemui.util.settings.SecureSettings -import java.io.PrintWriter -import java.util.concurrent.Executor -import javax.inject.Inject - -private const val TAG = "AutoAddTracker" -private const val DELIMITER = "," - -/** - * Class to track tiles that have been auto-added - * - * The list is backed by [Settings.Secure.QS_AUTO_ADDED_TILES]. - * - * It also handles restore gracefully. - */ -class AutoAddTracker -@VisibleForTesting -constructor( - private val secureSettings: SecureSettings, - private val broadcastDispatcher: BroadcastDispatcher, - private val qsHost: QSHost, - private val dumpManager: DumpManager, - private val mainHandler: Handler?, - private val backgroundExecutor: Executor, - private var userId: Int -) : UserAwareController, Dumpable { - - companion object { - private val FILTER = IntentFilter(Intent.ACTION_SETTING_RESTORED) - } - - @GuardedBy("autoAdded") private val autoAdded = ArraySet<String>() - private var restoredTiles: Map<String, AutoTile>? = null - - override val currentUserId: Int - get() = userId - - private val contentObserver = - object : ContentObserver(mainHandler) { - override fun onChange( - selfChange: Boolean, - uris: Collection<Uri>, - flags: Int, - _userId: Int - ) { - if (_userId != userId) { - // Ignore changes outside of our user. We'll load the correct value on user - // change - return - } - loadTiles() - } - } - - private val restoreReceiver = - object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - if (intent.action != Intent.ACTION_SETTING_RESTORED) return - processRestoreIntent(intent) - } - } - - private fun processRestoreIntent(intent: Intent) { - when (intent.getStringExtra(Intent.EXTRA_SETTING_NAME)) { - Settings.Secure.QS_TILES -> { - restoredTiles = - intent - .getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE) - ?.split(DELIMITER) - ?.mapIndexed(::AutoTile) - ?.associateBy(AutoTile::tileType) - ?: run { - Log.w(TAG, "Null restored tiles for user $userId") - emptyMap() - } - } - Settings.Secure.QS_AUTO_ADDED_TILES -> { - restoredTiles?.let { restoredTiles -> - val restoredAutoAdded = - intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE)?.split(DELIMITER) - ?: emptyList() - val autoAddedBeforeRestore = - intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE)?.split(DELIMITER) - ?: emptyList() - - val tilesToRemove = restoredAutoAdded.filter { it !in restoredTiles } - if (tilesToRemove.isNotEmpty()) { - Log.d(TAG, "Removing tiles: $tilesToRemove") - qsHost.removeTiles(tilesToRemove) - } - val tiles = - synchronized(autoAdded) { - autoAdded.clear() - autoAdded.addAll(restoredAutoAdded + autoAddedBeforeRestore) - getTilesFromListLocked() - } - saveTiles(tiles) - } - ?: run { - Log.w( - TAG, - "${Settings.Secure.QS_AUTO_ADDED_TILES} restored before " + - "${Settings.Secure.QS_TILES} for user $userId" - ) - } - } - else -> {} // Do nothing for other Settings - } - } - - /** Init method must be called after construction to start listening */ - fun initialize() { - dumpManager.registerDumpable(TAG, this) - loadTiles() - secureSettings.registerContentObserverForUserSync( - secureSettings.getUriFor(Settings.Secure.QS_AUTO_ADDED_TILES), - contentObserver, - UserHandle.USER_ALL - ) - registerBroadcastReceiver() - } - - /** Unregister listeners, receivers and observers */ - fun destroy() { - dumpManager.unregisterDumpable(TAG) - secureSettings.unregisterContentObserverSync(contentObserver) - unregisterBroadcastReceiver() - } - - private fun registerBroadcastReceiver() { - broadcastDispatcher.registerReceiver( - restoreReceiver, - FILTER, - backgroundExecutor, - UserHandle.of(userId) - ) - } - - private fun unregisterBroadcastReceiver() { - broadcastDispatcher.unregisterReceiver(restoreReceiver) - } - - override fun changeUser(newUser: UserHandle) { - if (newUser.identifier == userId) return - unregisterBroadcastReceiver() - userId = newUser.identifier - restoredTiles = null - loadTiles() - registerBroadcastReceiver() - } - - fun getRestoredTilePosition(tile: String): Int = - restoredTiles?.get(tile)?.index ?: QSHost.POSITION_AT_END - - /** Returns `true` if the tile has been auto-added before */ - fun isAdded(tile: String): Boolean { - return synchronized(autoAdded) { tile in autoAdded } - } - - /** - * Sets a tile as auto-added. - * - * From here on, [isAdded] will return true for that tile. - */ - fun setTileAdded(tile: String) { - val tiles = - synchronized(autoAdded) { - if (autoAdded.add(tile)) { - getTilesFromListLocked() - } else { - null - } - } - tiles?.let { saveTiles(it) } - } - - /** - * Removes a tile from the list of auto-added. - * - * This allows for this tile to be auto-added again in the future. - */ - fun setTileRemoved(tile: String) { - val tiles = - synchronized(autoAdded) { - if (autoAdded.remove(tile)) { - getTilesFromListLocked() - } else { - null - } - } - tiles?.let { saveTiles(it) } - } - - private fun getTilesFromListLocked(): String { - return TextUtils.join(DELIMITER, autoAdded) - } - - private fun saveTiles(tiles: String) { - secureSettings.putStringForUser( - Settings.Secure.QS_AUTO_ADDED_TILES, - tiles, - /* tag */ null, - /* makeDefault */ false, - userId, - /* overrideableByRestore */ true - ) - } - - private fun loadTiles() { - synchronized(autoAdded) { - autoAdded.clear() - autoAdded.addAll(getAdded()) - } - } - - private fun getAdded(): Collection<String> { - val current = secureSettings.getStringForUser(Settings.Secure.QS_AUTO_ADDED_TILES, userId) - return current?.split(DELIMITER) ?: emptySet() - } - - override fun dump(pw: PrintWriter, args: Array<out String>) { - pw.println("Current user: $userId") - pw.println("Restored tiles: $restoredTiles") - pw.println("Added tiles: $autoAdded") - } - - @SysUISingleton - class Builder - @Inject - constructor( - private val secureSettings: SecureSettings, - private val broadcastDispatcher: BroadcastDispatcher, - private val qsHost: QSHost, - private val dumpManager: DumpManager, - @Main private val handler: Handler, - @Background private val executor: Executor - ) { - private var userId: Int = 0 - - fun setUserId(_userId: Int): Builder { - userId = _userId - return this - } - - fun build(): AutoAddTracker { - return AutoAddTracker( - secureSettings, - broadcastDispatcher, - qsHost, - dumpManager, - handler, - executor, - userId - ) - } - } - - private data class AutoTile(val index: Int, val tileType: String) -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt index 9fa6769fe5f3..bb238f2e20fe 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentStartable.kt @@ -19,6 +19,7 @@ package com.android.systemui.qs import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.fragments.FragmentService +import com.android.systemui.qs.composefragment.QSFragmentCompose import dagger.Binds import dagger.Module import dagger.multibindings.ClassKey @@ -31,13 +32,18 @@ class QSFragmentStartable @Inject constructor( private val fragmentService: FragmentService, - private val qsFragmentLegacyProvider: Provider<QSFragmentLegacy> + private val qsFragmentLegacyProvider: Provider<QSFragmentLegacy>, + private val qsFragmentComposeProvider: Provider<QSFragmentCompose>, ) : CoreStartable { override fun start() { fragmentService.addFragmentInstantiationProvider( QSFragmentLegacy::class.java, qsFragmentLegacyProvider ) + fragmentService.addFragmentInstantiationProvider( + QSFragmentCompose::class.java, + qsFragmentComposeProvider + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt index c77233eb1737..4323b3199d57 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt @@ -47,12 +47,10 @@ import kotlinx.coroutines.launch class QSHostAdapter @Inject constructor( - private val qsTileHost: QSTileHost, private val interactor: CurrentTilesInteractor, private val context: Context, private val tileServiceRequestControllerBuilder: TileServiceRequestController.Builder, @Application private val scope: CoroutineScope, - flags: QSPipelineFlagsRepository, dumpManager: DumpManager, ) : QSHost { @@ -60,123 +58,69 @@ constructor( private const val TAG = "QSTileHost" } - private val useNewHost = flags.pipelineEnabled - @GuardedBy("callbacksMap") private val callbacksMap = mutableMapOf<QSHost.Callback, Job>() init { scope.launch { tileServiceRequestControllerBuilder.create(this@QSHostAdapter).init() } // Redirect dump to the correct host (needed for CTS tests) - dumpManager.registerCriticalDumpable(TAG, if (useNewHost) interactor else qsTileHost) + dumpManager.registerCriticalDumpable(TAG, interactor) } override fun getTiles(): Collection<QSTile> { - return if (useNewHost) { - interactor.currentQSTiles - } else { - qsTileHost.getTiles() - } + return interactor.currentQSTiles } override fun getSpecs(): List<String> { - return if (useNewHost) { - interactor.currentTilesSpecs.map { it.spec } - } else { - qsTileHost.getSpecs() - } + return interactor.currentTilesSpecs.map { it.spec } } override fun removeTile(spec: String) { - if (useNewHost) { - interactor.removeTiles(listOf(TileSpec.create(spec))) - } else { - qsTileHost.removeTile(spec) - } + interactor.removeTiles(listOf(TileSpec.create(spec))) } override fun addCallback(callback: QSHost.Callback) { - if (useNewHost) { - val job = scope.launch { interactor.currentTiles.collect { callback.onTilesChanged() } } - synchronized(callbacksMap) { callbacksMap.put(callback, job) } - } else { - qsTileHost.addCallback(callback) - } + val job = scope.launch { interactor.currentTiles.collect { callback.onTilesChanged() } } + synchronized(callbacksMap) { callbacksMap.put(callback, job) } } override fun removeCallback(callback: QSHost.Callback) { - if (useNewHost) { - synchronized(callbacksMap) { callbacksMap.remove(callback)?.cancel() } - } else { - qsTileHost.removeCallback(callback) - } + synchronized(callbacksMap) { callbacksMap.remove(callback)?.cancel() } } override fun removeTiles(specs: Collection<String>) { - if (useNewHost) { - interactor.removeTiles(specs.map(TileSpec::create)) - } else { - qsTileHost.removeTiles(specs) - } + interactor.removeTiles(specs.map(TileSpec::create)) } override fun removeTileByUser(component: ComponentName) { - if (useNewHost) { - interactor.removeTiles(listOf(TileSpec.create(component))) - } else { - qsTileHost.removeTileByUser(component) - } + interactor.removeTiles(listOf(TileSpec.create(component))) } override fun addTile(spec: String, position: Int) { - if (useNewHost) { - interactor.addTile(TileSpec.create(spec), position) - } else { - qsTileHost.addTile(spec, position) - } + interactor.addTile(TileSpec.create(spec), position) } override fun addTile(component: ComponentName, end: Boolean) { - if (useNewHost) { - interactor.addTile(TileSpec.create(component), if (end) POSITION_AT_END else 0) - } else { - qsTileHost.addTile(component, end) - } + interactor.addTile(TileSpec.create(component), if (end) POSITION_AT_END else 0) } override fun changeTilesByUser(previousTiles: List<String>, newTiles: List<String>) { - if (useNewHost) { - interactor.setTiles(newTiles.map(TileSpec::create)) - } else { - qsTileHost.changeTilesByUser(previousTiles, newTiles) - } + interactor.setTiles(newTiles.map(TileSpec::create)) } override fun getContext(): Context { - return if (useNewHost) { - context - } else { - qsTileHost.context - } + return context } override fun getUserContext(): Context { - return if (useNewHost) { - interactor.userContext.value - } else { - qsTileHost.userContext - } + return interactor.userContext.value } override fun getUserId(): Int { - return if (useNewHost) { - interactor.userId.value - } else { - qsTileHost.userId - } + return interactor.userId.value } override fun createTile(tileSpec: String): QSTile? { - return qsTileHost.createTile(tileSpec) + return interactor.createTileSync(TileSpec.create(tileSpec)) } override fun addTile(spec: String) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt b/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt new file mode 100644 index 000000000000..1891c41f364b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs + +import com.android.internal.logging.UiEvent +import com.android.internal.logging.UiEventLogger + +/** Events of user interactions with modes from the QS Modes dialog. {@see ModesDialogViewModel} */ +enum class QSModesEvent(private val _id: Int) : UiEventLogger.UiEventEnum { + @UiEvent(doc = "User turned manual Do Not Disturb on via modes dialog") QS_MODES_DND_ON(1870), + @UiEvent(doc = "User turned manual Do Not Disturb off via modes dialog") QS_MODES_DND_OFF(1871), + @UiEvent(doc = "User opened mode settings from the Do Not Disturb tile in the modes dialog") + QS_MODES_DND_SETTINGS(1872), + @UiEvent(doc = "User turned automatic mode on via modes dialog") QS_MODES_MODE_ON(1873), + @UiEvent(doc = "User turned automatic mode off via modes dialog") QS_MODES_MODE_OFF(1874), + @UiEvent(doc = "User opened mode settings from a mode tile in the modes dialog") + QS_MODES_MODE_SETTINGS(1875), + @UiEvent(doc = "User clicked on Settings from the modes dialog") QS_MODES_SETTINGS(1876), + @UiEvent(doc = "User clicked on Do Not Disturb tile, opening the time selection dialog") + QS_MODES_DURATION_DIALOG(1879); + + override fun getId() = _id +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java deleted file mode 100644 index 03c2aa6f4bc4..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.qs; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings.Secure; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; - -import androidx.annotation.MainThread; -import androidx.annotation.Nullable; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.Dumpable; -import com.android.systemui.ProtoDumpable; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dump.nano.SystemUIProtoDump; -import com.android.systemui.plugins.PluginListener; -import com.android.systemui.plugins.PluginManager; -import com.android.systemui.plugins.qs.QSFactory; -import com.android.systemui.plugins.qs.QSTile; -import com.android.systemui.qs.external.CustomTile; -import com.android.systemui.qs.external.CustomTileStatePersister; -import com.android.systemui.qs.external.TileLifecycleManager; -import com.android.systemui.qs.external.TileServiceKey; -import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.qs.nano.QsTileState; -import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository; -import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; -import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository; -import com.android.systemui.qs.tiles.di.NewQSTileFactory; -import com.android.systemui.res.R; -import com.android.systemui.settings.UserFileManager; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.shade.ShadeController; -import com.android.systemui.statusbar.phone.AutoTileManager; -import com.android.systemui.tuner.TunerService; -import com.android.systemui.tuner.TunerService.Tunable; -import com.android.systemui.util.settings.SecureSettings; - -import dagger.Lazy; - -import org.jetbrains.annotations.NotNull; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.inject.Inject; -import javax.inject.Provider; - -/** Platform implementation of the quick settings tile host - * - * This class keeps track of the set of current tiles and is the in memory source of truth - * (ground truth is kept in {@link Secure#QS_TILES}). When the ground truth changes, - * {@link #onTuningChanged} will be called and the tiles will be re-created as needed. - * - * This class also provides the interface for adding/removing/changing tiles. - */ -@SysUISingleton -public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, ProtoDumpable, - PanelInteractor, CustomTileAddedRepository { - private static final String TAG = "QSTileHost"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - // Shared prefs that hold tile lifecycle info. - @VisibleForTesting - static final String TILES = "tiles_prefs"; - - private final Context mContext; - private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>(); - private final ArrayList<String> mTileSpecs = new ArrayList<>(); - private final TunerService mTunerService; - private final PluginManager mPluginManager; - private final QSLogger mQSLogger; - private final CustomTileStatePersister mCustomTileStatePersister; - private final Executor mMainExecutor; - private final UserFileManager mUserFileManager; - - private final List<Callback> mCallbacks = new ArrayList<>(); - @Nullable - private AutoTileManager mAutoTiles; - private final ArrayList<QSFactory> mQsFactories = new ArrayList<>(); - private int mCurrentUser; - private final Lazy<ShadeController> mShadeControllerProvider; - private Context mUserContext; - private UserTracker mUserTracker; - private SecureSettings mSecureSettings; - // Keep track of whether mTilesList contains the same information as the Settings value. - // This is a performance optimization to reduce the number of blocking calls to Settings from - // main thread. - // This is enforced by only cleaning the flag at the end of a successful run of #onTuningChanged - private boolean mTilesListDirty = true; - - private TileLifecycleManager.Factory mTileLifeCycleManagerFactory; - - private final QSPipelineFlagsRepository mFeatureFlags; - - @Inject - public QSTileHost(Context context, - Lazy<NewQSTileFactory> newQsTileFactoryProvider, - QSFactory defaultFactory, - @Main Executor mainExecutor, - PluginManager pluginManager, - TunerService tunerService, - Provider<AutoTileManager> autoTiles, - Lazy<ShadeController> shadeControllerProvider, - QSLogger qsLogger, - UserTracker userTracker, - SecureSettings secureSettings, - CustomTileStatePersister customTileStatePersister, - TileLifecycleManager.Factory tileLifecycleManagerFactory, - UserFileManager userFileManager, - QSPipelineFlagsRepository featureFlags - ) { - mContext = context; - mUserContext = context; - mTunerService = tunerService; - mPluginManager = pluginManager; - mQSLogger = qsLogger; - mMainExecutor = mainExecutor; - mTileLifeCycleManagerFactory = tileLifecycleManagerFactory; - mUserFileManager = userFileManager; - mFeatureFlags = featureFlags; - - mShadeControllerProvider = shadeControllerProvider; - - if (featureFlags.getTilesEnabled()) { - mQsFactories.add(newQsTileFactoryProvider.get()); - } - mQsFactories.add(defaultFactory); - pluginManager.addPluginListener(this, QSFactory.class, true); - mUserTracker = userTracker; - mCurrentUser = userTracker.getUserId(); - mSecureSettings = secureSettings; - mCustomTileStatePersister = customTileStatePersister; - - mainExecutor.execute(() -> { - // This is technically a hack to avoid circular dependency of - // QSTileHost -> XXXTile -> QSTileHost. Posting ensures creation - // finishes before creating any tiles. - tunerService.addTunable(this, TILES_SETTING); - // AutoTileManager can modify mTiles so make sure mTiles has already been initialized. - if (!mFeatureFlags.getPipelineEnabled()) { - mAutoTiles = autoTiles.get(); - } - }); - } - - public void destroy() { - mTiles.values().forEach(tile -> tile.destroy()); - mAutoTiles.destroy(); - mTunerService.removeTunable(this); - mPluginManager.removePluginListener(this); - } - - @Override - public void onPluginConnected(QSFactory plugin, Context pluginContext) { - // Give plugins priority over creation so they can override if they wish. - mQsFactories.add(0, plugin); - String value = mTunerService.getValue(TILES_SETTING); - // Force remove and recreate of all tiles. - onTuningChanged(TILES_SETTING, ""); - onTuningChanged(TILES_SETTING, value); - } - - @Override - public void onPluginDisconnected(QSFactory plugin) { - mQsFactories.remove(plugin); - // Force remove and recreate of all tiles. - String value = mTunerService.getValue(TILES_SETTING); - onTuningChanged(TILES_SETTING, ""); - onTuningChanged(TILES_SETTING, value); - } - - @Override - public void addCallback(Callback callback) { - mCallbacks.add(callback); - } - - @Override - public void removeCallback(Callback callback) { - mCallbacks.remove(callback); - } - - @Override - public Collection<QSTile> getTiles() { - return mTiles.values(); - } - - @Override - public void collapsePanels() { - mShadeControllerProvider.get().postAnimateCollapseShade(); - } - - @Override - public void forceCollapsePanels() { - mShadeControllerProvider.get().postAnimateForceCollapseShade(); - } - - @Override - public void openPanels() { - mShadeControllerProvider.get().postAnimateExpandQs(); - } - - @Override - public Context getContext() { - return mContext; - } - - @Override - public Context getUserContext() { - return mUserContext; - } - - @Override - public int getUserId() { - return mCurrentUser; - } - - public int indexOf(String spec) { - return mTileSpecs.indexOf(spec); - } - - /** - * Whenever the Secure Setting keeping track of the current tiles changes (or upon start) this - * will be called with the new value of the setting. - * - * This method will do the following: - * <ol> - * <li>Destroy any existing tile that's not one of the current tiles (in the setting)</li> - * <li>Create new tiles for those that don't already exist. If this tiles end up being - * not available, they'll also be destroyed.</li> - * <li>Save the resolved list of tiles (current tiles that are available) into the setting. - * This means that after this call ends, the tiles in the Setting, {@link #mTileSpecs}, - * and visible tiles ({@link #mTiles}) must match. - * </li> - * </ol> - * - * Additionally, if the user has changed, it'll do the following: - * <ul> - * <li>Change the user for SystemUI tiles: {@link QSTile#userSwitch}.</li> - * <li>Destroy any {@link CustomTile} and recreate it for the new user.</li> - * </ul> - * - * This happens in main thread as {@link com.android.systemui.tuner.TunerServiceImpl} dispatches - * in main thread. - * - * @see QSTile#isAvailable - */ - @MainThread - @Override - public void onTuningChanged(String key, String newValue) { - if (!TILES_SETTING.equals(key)) { - return; - } - int currentUser = mUserTracker.getUserId(); - if (currentUser != mCurrentUser) { - mUserContext = mUserTracker.getUserContext(); - if (mAutoTiles != null) { - mAutoTiles.changeUser(UserHandle.of(currentUser)); - } - } - // Do not process tiles if the flag is enabled. - if (mFeatureFlags.getPipelineEnabled()) { - return; - } - QSPipelineFlagsRepository.Utils.assertInLegacyMode(); - if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) { - newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode); - } - final List<String> tileSpecs = loadTileSpecs(mContext, newValue); - if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return; - Log.d(TAG, "Recreating tiles: " + tileSpecs); - mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach( - tile -> { - Log.d(TAG, "Destroying tile: " + tile.getKey()); - mQSLogger.logTileDestroyed(tile.getKey(), "Tile removed"); - tile.getValue().destroy(); - }); - final LinkedHashMap<String, QSTile> newTiles = new LinkedHashMap<>(); - for (String tileSpec : tileSpecs) { - QSTile tile = mTiles.get(tileSpec); - if (tile != null && (!(tile instanceof CustomTile) - || ((CustomTile) tile).getUser() == currentUser)) { - if (tile.isAvailable()) { - Log.d(TAG, "Adding " + tile); - tile.removeCallbacks(); - if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) { - tile.userSwitch(currentUser); - } - newTiles.put(tileSpec, tile); - mQSLogger.logTileAdded(tileSpec); - } else { - tile.destroy(); - Log.d(TAG, "Destroying not available tile: " + tileSpec); - mQSLogger.logTileDestroyed(tileSpec, "Tile not available"); - } - } else { - // This means that the tile is a CustomTile AND the user is different, so let's - // destroy it - if (tile != null) { - tile.destroy(); - Log.d(TAG, "Destroying tile for wrong user: " + tileSpec); - mQSLogger.logTileDestroyed(tileSpec, "Tile for wrong user"); - } - Log.d(TAG, "Creating tile: " + tileSpec); - try { - tile = createTile(tileSpec); - if (tile != null) { - if (tile.isAvailable()) { - newTiles.put(tileSpec, tile); - mQSLogger.logTileAdded(tileSpec); - } else { - tile.destroy(); - Log.d(TAG, "Destroying not available tile: " + tileSpec); - mQSLogger.logTileDestroyed(tileSpec, "Tile not available"); - } - } else { - Log.d(TAG, "No factory for a spec: " + tileSpec); - } - } catch (Throwable t) { - Log.w(TAG, "Error creating tile for spec: " + tileSpec, t); - } - } - } - mCurrentUser = currentUser; - List<String> currentSpecs = new ArrayList<>(mTileSpecs); - mTileSpecs.clear(); - mTileSpecs.addAll(newTiles.keySet()); // Only add the valid (available) tiles. - mTiles.clear(); - mTiles.putAll(newTiles); - if (newTiles.isEmpty() && !tileSpecs.isEmpty()) { - // If we didn't manage to create any tiles, set it to empty (default) - Log.d(TAG, "No valid tiles on tuning changed. Setting to default."); - changeTilesByUser(currentSpecs, loadTileSpecs(mContext, "")); - } else { - String resolvedTiles = TextUtils.join(",", mTileSpecs); - if (!resolvedTiles.equals(newValue)) { - // If the resolved tiles (those we actually ended up with) are different than - // the ones that are in the setting, update the Setting. - saveTilesToSettings(mTileSpecs); - } - mTilesListDirty = false; - for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).onTilesChanged(); - } - } - } - - /** - * Only use with [CustomTile] if the tile doesn't exist anymore (and therefore doesn't need - * its lifecycle terminated). - */ - @Override - public void removeTile(String spec) { - if (spec.startsWith(CustomTile.PREFIX)) { - // If the tile is removed (due to it not actually existing), mark it as removed. That - // way it will be marked as newly added if it appears in the future. - setTileAdded(CustomTile.getComponentFromSpec(spec), mCurrentUser, false); - } - mMainExecutor.execute(() -> changeTileSpecs(tileSpecs-> tileSpecs.remove(spec))); - } - - /** - * Remove many tiles at once. - * - * It will only save to settings once (as opposed to {@link QSTileHost#removeTileByUser} called - * multiple times). - */ - @Override - public void removeTiles(Collection<String> specs) { - mMainExecutor.execute(() -> changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs))); - } - - /** - * Add a tile to the end - * - * @param spec string matching a pre-defined tilespec - */ - public void addTile(String spec) { - addTile(spec, POSITION_AT_END); - } - - @Override - public void addTile(String spec, int requestPosition) { - mMainExecutor.execute(() -> - changeTileSpecs(tileSpecs -> { - if (tileSpecs.contains(spec)) return false; - - int size = tileSpecs.size(); - if (requestPosition == POSITION_AT_END || requestPosition >= size) { - tileSpecs.add(spec); - } else { - tileSpecs.add(requestPosition, spec); - } - return true; - }) - ); - } - - // When calling this, you may want to modify mTilesListDirty accordingly. - @MainThread - private void saveTilesToSettings(List<String> tileSpecs) { - Log.d(TAG, "Saving tiles: " + tileSpecs + " for user: " + mCurrentUser); - mSecureSettings.putStringForUser(TILES_SETTING, TextUtils.join(",", tileSpecs), - null /* tag */, false /* default */, mCurrentUser, - true /* overrideable by restore */); - } - - @MainThread - private void changeTileSpecs(Predicate<List<String>> changeFunction) { - final List<String> tileSpecs; - if (!mTilesListDirty) { - tileSpecs = new ArrayList<>(mTileSpecs); - } else { - tileSpecs = loadTileSpecs(mContext, - mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser)); - } - if (changeFunction.test(tileSpecs)) { - mTilesListDirty = true; - saveTilesToSettings(tileSpecs); - } - } - - @Override - public void addTile(ComponentName tile) { - addTile(tile, /* end */ false); - } - - @Override - public void addTile(ComponentName tile, boolean end) { - String spec = CustomTile.toSpec(tile); - addTile(spec, end ? POSITION_AT_END : 0); - } - - /** - * This will call through {@link #changeTilesByUser}. It should only be used when a tile is - * removed by a <b>user action</b> like {@code adb}. - */ - @Override - public void removeTileByUser(ComponentName tile) { - mMainExecutor.execute(() -> { - List<String> newSpecs = new ArrayList<>(mTileSpecs); - if (newSpecs.remove(CustomTile.toSpec(tile))) { - changeTilesByUser(mTileSpecs, newSpecs); - } - }); - } - - /** - * Change the tiles triggered by the user editing. - * <p> - * This is not called on device start, or on user change. - * - * {@link android.service.quicksettings.TileService#onTileRemoved} will be called for tiles - * that are removed. - */ - @MainThread - @Override - public void changeTilesByUser(List<String> previousTiles, List<String> newTiles) { - final List<String> copy = new ArrayList<>(previousTiles); - final int NP = copy.size(); - for (int i = 0; i < NP; i++) { - String tileSpec = copy.get(i); - if (!tileSpec.startsWith(CustomTile.PREFIX)) continue; - if (!newTiles.contains(tileSpec)) { - ComponentName component = CustomTile.getComponentFromSpec(tileSpec); - Intent intent = new Intent().setComponent(component); - TileLifecycleManager lifecycleManager = mTileLifeCycleManagerFactory.create( - intent, new UserHandle(mCurrentUser)); - lifecycleManager.onStopListening(); - lifecycleManager.onTileRemoved(); - mCustomTileStatePersister.removeState(new TileServiceKey(component, mCurrentUser)); - setTileAdded(component, mCurrentUser, false); - lifecycleManager.flushMessagesAndUnbind(); - } - } - Log.d(TAG, "saveCurrentTiles " + newTiles); - mTilesListDirty = true; - saveTilesToSettings(newTiles); - } - - @Nullable - @Override - public QSTile createTile(String tileSpec) { - for (int i = 0; i < mQsFactories.size(); i++) { - QSTile t = mQsFactories.get(i).createTile(tileSpec); - if (t != null) { - return t; - } - } - return null; - } - - /** - * Check if a particular {@link CustomTile} has been added for a user and has not been removed - * since. - * @param componentName the {@link ComponentName} of the - * {@link android.service.quicksettings.TileService} associated with the - * tile. - * @param userId the user to check - */ - @Override - public boolean isTileAdded(ComponentName componentName, int userId) { - return mUserFileManager - .getSharedPreferences(TILES, 0, userId) - .getBoolean(componentName.flattenToString(), false); - } - - /** - * Persists whether a particular {@link CustomTile} has been added and it's currently in the - * set of selected tiles ({@link #mTiles}. - * @param componentName the {@link ComponentName} of the - * {@link android.service.quicksettings.TileService} associated - * with the tile. - * @param userId the user for this tile - * @param added {@code true} if the tile is being added, {@code false} otherwise - */ - @Override - public void setTileAdded(ComponentName componentName, int userId, boolean added) { - mUserFileManager.getSharedPreferences(TILES, 0, userId) - .edit() - .putBoolean(componentName.flattenToString(), added) - .apply(); - } - - @Override - public List<String> getSpecs() { - return mTileSpecs; - } - - protected static List<String> loadTileSpecs(Context context, String tileList) { - final Resources res = context.getResources(); - - if (TextUtils.isEmpty(tileList)) { - tileList = res.getString(R.string.quick_settings_tiles); - Log.d(TAG, "Loaded tile specs from default config: " + tileList); - } else { - Log.d(TAG, "Loaded tile specs from setting: " + tileList); - } - final ArrayList<String> tiles = new ArrayList<String>(); - boolean addedDefault = false; - Set<String> addedSpecs = new ArraySet<>(); - for (String tile : tileList.split(",")) { - tile = tile.trim(); - if (tile.isEmpty()) continue; - if (tile.equals("default")) { - if (!addedDefault) { - List<String> defaultSpecs = QSHost.getDefaultSpecs(context.getResources()); - for (String spec : defaultSpecs) { - if (!addedSpecs.contains(spec)) { - tiles.add(spec); - addedSpecs.add(spec); - } - } - addedDefault = true; - } - } else { - if (!addedSpecs.contains(tile)) { - tiles.add(tile); - addedSpecs.add(tile); - } - } - } - - if (!tiles.contains("internet")) { - if (tiles.contains("wifi")) { - // Replace the WiFi with Internet, and remove the Cell - tiles.set(tiles.indexOf("wifi"), "internet"); - tiles.remove("cell"); - } else if (tiles.contains("cell")) { - // Replace the Cell with Internet - tiles.set(tiles.indexOf("cell"), "internet"); - } - } else { - tiles.remove("wifi"); - tiles.remove("cell"); - } - return tiles; - } - - @Override - public void dump(PrintWriter pw, String[] args) { - pw.println("QSTileHost:"); - pw.println("tile specs: " + mTileSpecs); - pw.println("current user: " + mCurrentUser); - pw.println("is dirty: " + mTilesListDirty); - pw.println("tiles:"); - mTiles.values().stream().filter(obj -> obj instanceof Dumpable) - .forEach(o -> ((Dumpable) o).dump(pw, args)); - } - - @Override - public void dumpProto(@NotNull SystemUIProtoDump systemUIProtoDump, @NotNull String[] args) { - List<QsTileState> data = mTiles.values().stream() - .map(QSTile::getState) - .map(TileStateToProtoKt::toProto) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - systemUIProtoDump.tiles = data.toArray(new QsTileState[0]); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index f207b1de3cba..bc695bdd4e05 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -34,6 +34,7 @@ import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.util.leak.RotationUtils; @@ -77,9 +78,11 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> @Override protected void onInit() { super.onInit(); - updateMediaExpansion(); - mMediaHost.setShowsOnlyActiveMedia(true); - mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); + if (!SceneContainerFlag.isEnabled()) { + updateMediaExpansion(); + mMediaHost.setShowsOnlyActiveMedia(true); + mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); + } } @Override @@ -125,7 +128,9 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> if (newMaxTiles != mView.getNumQuickTiles()) { setMaxTiles(newMaxTiles); } - updateMediaExpansion(); + if (!SceneContainerFlag.isEnabled()) { + updateMediaExpansion(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt new file mode 100644 index 000000000000..5d81d4f3f9ec --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.composefragment + +import android.annotation.SuppressLint +import android.graphics.Rect +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.OnBackPressedDispatcher +import androidx.activity.OnBackPressedDispatcherOwner +import androidx.activity.setViewTreeOnBackPressedDispatcherOwner +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.layout +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInRoot +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.round +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.android.compose.modifiers.height +import com.android.compose.modifiers.padding +import com.android.compose.theme.PlatformTheme +import com.android.systemui.compose.modifiers.sysuiResTag +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.plugins.qs.QS +import com.android.systemui.plugins.qs.QSContainerController +import com.android.systemui.qs.composefragment.viewmodel.QSFragmentComposeViewModel +import com.android.systemui.qs.flags.QSComposeFragment +import com.android.systemui.qs.footer.ui.compose.FooterActions +import com.android.systemui.qs.panels.ui.compose.QuickQuickSettings +import com.android.systemui.qs.ui.composable.QuickSettingsTheme +import com.android.systemui.qs.ui.composable.ShadeBody +import com.android.systemui.res.R +import com.android.systemui.util.LifecycleFragment +import java.util.function.Consumer +import javax.inject.Inject +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +@SuppressLint("ValidFragment") +class QSFragmentCompose +@Inject +constructor( + private val qsFragmentComposeViewModelFactory: QSFragmentComposeViewModel.Factory, +) : LifecycleFragment(), QS { + + private val scrollListener = MutableStateFlow<QS.ScrollListener?>(null) + private val heightListener = MutableStateFlow<QS.HeightListener?>(null) + private val qsContainerController = MutableStateFlow<QSContainerController?>(null) + + private lateinit var viewModel: QSFragmentComposeViewModel + + // Starting with a non-zero value makes it so that it has a non-zero height on first expansion + // This is important for `QuickSettingsControllerImpl.mMinExpansionHeight` to detect a "change". + private val qqsHeight = MutableStateFlow(1) + private val qsHeight = MutableStateFlow(0) + private val qqsVisible = MutableStateFlow(false) + private val qqsPositionOnRoot = Rect() + private val composeViewPositionOnScreen = Rect() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + QSComposeFragment.isUnexpectedlyInLegacyMode() + viewModel = qsFragmentComposeViewModelFactory.create(lifecycleScope) + + setListenerCollections() + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val context = inflater.context + return ComposeView(context).apply { + setBackPressedDispatcher() + setContent { + PlatformTheme { + val visible by viewModel.qsVisible.collectAsStateWithLifecycle() + val qsState by viewModel.expansionState.collectAsStateWithLifecycle() + + AnimatedVisibility( + visible = visible, + modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars) + ) { + AnimatedContent(targetState = qsState) { + when (it) { + QSFragmentComposeViewModel.QSExpansionState.QQS -> { + QuickQuickSettingsElement() + } + QSFragmentComposeViewModel.QSExpansionState.QS -> { + QuickSettingsElement() + } + else -> {} + } + } + } + } + } + } + } + + override fun setPanelView(notificationPanelView: QS.HeightListener?) { + heightListener.value = notificationPanelView + } + + override fun hideImmediately() { + // view?.animate()?.cancel() + // view?.y = -qsMinExpansionHeight.toFloat() + } + + override fun getQsMinExpansionHeight(): Int { + // TODO (b/353253277) implement split screen + return qqsHeight.value + } + + override fun getDesiredHeight(): Int { + /* + * Looking at the code, it seems that + * * If customizing, then the height is that of the view post-layout, which is set by + * QSContainerImpl.calculateContainerHeight, which is the height the customizer takes + * * If not customizing, it's the measured height. So we may want to surface that. + */ + return view?.height ?: 0 + } + + override fun setHeightOverride(desiredHeight: Int) { + viewModel.heightOverrideValue = desiredHeight + } + + override fun setHeaderClickable(qsExpansionEnabled: Boolean) { + // Empty method + } + + override fun isCustomizing(): Boolean { + return viewModel.containerViewModel.editModeViewModel.isEditing.value + } + + override fun closeCustomizer() { + viewModel.containerViewModel.editModeViewModel.stopEditing() + } + + override fun setOverscrolling(overscrolling: Boolean) { + viewModel.stackScrollerOverscrollingValue = overscrolling + } + + override fun setExpanded(qsExpanded: Boolean) { + viewModel.isQSExpanded = qsExpanded + } + + override fun setListening(listening: Boolean) { + // Not needed, views start listening and collection when composed + } + + override fun setQsVisible(qsVisible: Boolean) { + viewModel.isQSVisible = qsVisible + } + + override fun isShowingDetail(): Boolean { + return isCustomizing + } + + override fun closeDetail() { + closeCustomizer() + } + + override fun animateHeaderSlidingOut() { + // TODO(b/353254353) + } + + override fun setQsExpansion( + qsExpansionFraction: Float, + panelExpansionFraction: Float, + headerTranslation: Float, + squishinessFraction: Float + ) { + viewModel.qsExpansionValue = qsExpansionFraction + viewModel.panelExpansionFractionValue = panelExpansionFraction + viewModel.squishinessFractionValue = squishinessFraction + + // TODO(b/353254353) Handle header translation + } + + override fun setHeaderListening(listening: Boolean) { + // Not needed, header will start listening as soon as it's composed + } + + override fun notifyCustomizeChanged() { + // Not needed, only called from inside customizer + } + + override fun setContainerController(controller: QSContainerController?) { + qsContainerController.value = controller + } + + override fun setCollapseExpandAction(action: Runnable?) { + // Nothing to do yet. But this should be wired to a11y + } + + override fun getHeightDiff(): Int { + return 0 // For now TODO(b/353254353) + } + + override fun getHeader(): View? { + QSComposeFragment.isUnexpectedlyInLegacyMode() + return null + } + + override fun setShouldUpdateSquishinessOnMedia(shouldUpdate: Boolean) { + super.setShouldUpdateSquishinessOnMedia(shouldUpdate) + // TODO (b/353253280) + } + + override fun setInSplitShade(shouldTranslate: Boolean) { + // TODO (b/356435605) + } + + override fun setTransitionToFullShadeProgress( + isTransitioningToFullShade: Boolean, + qsTransitionFraction: Float, + qsSquishinessFraction: Float + ) { + super.setTransitionToFullShadeProgress( + isTransitioningToFullShade, + qsTransitionFraction, + qsSquishinessFraction + ) + } + + override fun setFancyClipping( + leftInset: Int, + top: Int, + rightInset: Int, + bottom: Int, + cornerRadius: Int, + visible: Boolean, + fullWidth: Boolean + ) {} + + override fun isFullyCollapsed(): Boolean { + return !viewModel.isQSVisible + } + + override fun setCollapsedMediaVisibilityChangedListener(listener: Consumer<Boolean>?) { + // TODO (b/353253280) + } + + override fun setScrollListener(scrollListener: QS.ScrollListener?) { + this.scrollListener.value = scrollListener + } + + override fun setOverScrollAmount(overScrollAmount: Int) { + super.setOverScrollAmount(overScrollAmount) + } + + override fun setIsNotificationPanelFullWidth(isFullWidth: Boolean) { + viewModel.isSmallScreenValue = isFullWidth + } + + override fun getHeaderTop(): Int { + return viewModel.qqsHeaderHeight.value + } + + override fun getHeaderBottom(): Int { + return headerTop + qqsHeight.value + } + + override fun getHeaderLeft(): Int { + return qqsPositionOnRoot.left + } + + override fun getHeaderBoundsOnScreen(outBounds: Rect) { + outBounds.set(qqsPositionOnRoot) + view?.getBoundsOnScreen(composeViewPositionOnScreen) + ?: run { composeViewPositionOnScreen.setEmpty() } + qqsPositionOnRoot.offset(composeViewPositionOnScreen.left, composeViewPositionOnScreen.top) + } + + override fun isHeaderShown(): Boolean { + return qqsVisible.value + } + + private fun setListenerCollections() { + lifecycleScope.launch { + lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + launch { + // TODO + // setListenerJob( + // scrollListener, + // + // ) + } + launch { + setListenerJob( + heightListener, + viewModel.containerViewModel.editModeViewModel.isEditing + ) { + onQsHeightChanged() + } + } + launch { + setListenerJob( + qsContainerController, + viewModel.containerViewModel.editModeViewModel.isEditing + ) { + setCustomizerShowing(it) + } + } + } + } + } + + @Composable + private fun QuickQuickSettingsElement() { + val qqsPadding by viewModel.qqsHeaderHeight.collectAsStateWithLifecycle() + DisposableEffect(Unit) { + qqsVisible.value = true + + onDispose { qqsVisible.value = false } + } + Column(modifier = Modifier.sysuiResTag("quick_qs_panel")) { + QuickQuickSettings( + viewModel = viewModel.containerViewModel.quickQuickSettingsViewModel, + modifier = + Modifier.onGloballyPositioned { coordinates -> + val (leftFromRoot, topFromRoot) = coordinates.positionInRoot().round() + val (width, height) = coordinates.size + qqsPositionOnRoot.set( + leftFromRoot, + topFromRoot, + leftFromRoot + width, + topFromRoot + height + ) + } + .layout { measurable, constraints -> + val placeable = measurable.measure(constraints) + qqsHeight.value = placeable.height + + layout(placeable.width, placeable.height) { placeable.place(0, 0) } + } + .padding(top = { qqsPadding }) + ) + Spacer(modifier = Modifier.weight(1f)) + } + } + + @Composable + private fun QuickSettingsElement() { + val qqsPadding by viewModel.qqsHeaderHeight.collectAsStateWithLifecycle() + val qsExtraPadding = dimensionResource(R.dimen.qs_panel_padding_top) + Column { + Box(modifier = Modifier.fillMaxSize().weight(1f)) { + Column { + Spacer(modifier = Modifier.height { qqsPadding + qsExtraPadding.roundToPx() }) + ShadeBody(viewModel = viewModel.containerViewModel) + } + } + QuickSettingsTheme { + FooterActions( + viewModel = viewModel.footerActionsViewModel, + qsVisibilityLifecycleOwner = this@QSFragmentCompose, + modifier = Modifier.sysuiResTag("qs_footer_actions") + ) + } + } + } +} + +private fun View.setBackPressedDispatcher() { + repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + setViewTreeOnBackPressedDispatcherOwner( + object : OnBackPressedDispatcherOwner { + override val onBackPressedDispatcher = + OnBackPressedDispatcher().apply { + setOnBackInvokedDispatcher(it.viewRootImpl.onBackInvokedDispatcher) + } + + override val lifecycle: Lifecycle = this@repeatWhenAttached.lifecycle + } + ) + } + } +} + +private suspend inline fun <Listener : Any, Data> setListenerJob( + listenerFlow: MutableStateFlow<Listener?>, + dataFlow: Flow<Data>, + crossinline onCollect: suspend Listener.(Data) -> Unit +) { + coroutineScope { + try { + listenerFlow.collectLatest { listenerOrNull -> + listenerOrNull?.let { currentListener -> + launch { + // Called when editing mode changes + dataFlow.collect { currentListener.onCollect(it) } + } + } + } + awaitCancellation() + } finally { + listenerFlow.value = null + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt new file mode 100644 index 000000000000..9e109e436226 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.composefragment.viewmodel + +import android.content.res.Resources +import android.graphics.Rect +import androidx.lifecycle.LifecycleCoroutineScope +import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel +import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel +import com.android.systemui.shade.LargeScreenHeaderHelper +import com.android.systemui.shade.transition.LargeScreenShadeInterpolator +import com.android.systemui.statusbar.SysuiStatusBarStateController +import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository +import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.util.LargeScreenUtils +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch + +class QSFragmentComposeViewModel +@AssistedInject +constructor( + val containerViewModel: QuickSettingsContainerViewModel, + @Main private val resources: Resources, + private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, + private val footerActionsController: FooterActionsController, + private val sysuiStatusBarStateController: SysuiStatusBarStateController, + private val keyguardBypassController: KeyguardBypassController, + private val disableFlagsRepository: DisableFlagsRepository, + private val largeScreenShadeInterpolator: LargeScreenShadeInterpolator, + private val configurationInteractor: ConfigurationInteractor, + private val largeScreenHeaderHelper: LargeScreenHeaderHelper, + @Assisted private val lifecycleScope: LifecycleCoroutineScope, +) { + val footerActionsViewModel = + footerActionsViewModelFactory.create(lifecycleScope).also { + lifecycleScope.launch { footerActionsController.init() } + } + + private val _qsBounds = MutableStateFlow(Rect()) + + private val _qsExpanded = MutableStateFlow(false) + var isQSExpanded: Boolean + get() = _qsExpanded.value + set(value) { + _qsExpanded.value = value + } + + private val _qsVisible = MutableStateFlow(false) + val qsVisible = _qsVisible.asStateFlow() + var isQSVisible: Boolean + get() = qsVisible.value + set(value) { + _qsVisible.value = value + } + + private val _qsExpansion = MutableStateFlow(0f) + var qsExpansionValue: Float + get() = _qsExpansion.value + set(value) { + _qsExpansion.value = value + } + + private val _panelFraction = MutableStateFlow(0f) + var panelExpansionFractionValue: Float + get() = _panelFraction.value + set(value) { + _panelFraction.value = value + } + + private val _squishinessFraction = MutableStateFlow(0f) + var squishinessFractionValue: Float + get() = _squishinessFraction.value + set(value) { + _squishinessFraction.value = value + } + + val qqsHeaderHeight = + configurationInteractor.onAnyConfigurationChange + .map { + if (LargeScreenUtils.shouldUseLargeScreenShadeHeader(resources)) { + 0 + } else { + largeScreenHeaderHelper.getLargeScreenHeaderHeight() + } + } + .stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), 0) + + private val _headerAnimating = MutableStateFlow(false) + + private val _stackScrollerOverscrolling = MutableStateFlow(false) + var stackScrollerOverscrollingValue: Boolean + get() = _stackScrollerOverscrolling.value + set(value) { + _stackScrollerOverscrolling.value = value + } + + private val qsDisabled = + disableFlagsRepository.disableFlags + .map { !it.isQuickSettingsEnabled() } + .stateIn( + lifecycleScope, + SharingStarted.WhileSubscribed(), + !disableFlagsRepository.disableFlags.value.isQuickSettingsEnabled() + ) + + private val _showCollapsedOnKeyguard = MutableStateFlow(false) + + private val _keyguardAndExpanded = MutableStateFlow(false) + + private val _statusBarState = MutableStateFlow(-1) + + private val _viewHeight = MutableStateFlow(0) + + private val _headerTranslation = MutableStateFlow(0f) + + private val _inSplitShade = MutableStateFlow(false) + + private val _transitioningToFullShade = MutableStateFlow(false) + + private val _lockscreenToShadeProgress = MutableStateFlow(false) + + private val _overscrolling = MutableStateFlow(false) + + private val _isSmallScreen = MutableStateFlow(false) + var isSmallScreenValue: Boolean + get() = _isSmallScreen.value + set(value) { + _isSmallScreen.value = value + } + + private val _shouldUpdateMediaSquishiness = MutableStateFlow(false) + + private val _heightOverride = MutableStateFlow(-1) + val heightOverride = _heightOverride.asStateFlow() + var heightOverrideValue: Int + get() = heightOverride.value + set(value) { + _heightOverride.value = value + } + + val expansionState: StateFlow<QSExpansionState> = + combine( + _stackScrollerOverscrolling, + _qsExpanded, + _qsExpansion, + ) { args: Array<Any> -> + val expansion = args[2] as Float + if (expansion > 0.5f) { + QSExpansionState.QS + } else { + QSExpansionState.QQS + } + } + .stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), QSExpansionState.QQS) + + @AssistedFactory + interface Factory { + fun create(lifecycleScope: LifecycleCoroutineScope): QSFragmentComposeViewModel + } + + sealed interface QSExpansionState { + data object QQS : QSExpansionState + + data object QS : QSExpansionState + + @JvmInline value class Expanding(val progress: Float) : QSExpansionState + + @JvmInline value class Collapsing(val progress: Float) : QSExpansionState + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt index 496a6f830e8c..a947d361a432 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt @@ -18,17 +18,14 @@ package com.android.systemui.qs.dagger import com.android.systemui.qs.QSHost import com.android.systemui.qs.QSHostAdapter -import com.android.systemui.qs.QSTileHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.QsEventLoggerImpl import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedSharedPrefsRepository import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractorImpl -import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository import dagger.Binds import dagger.Module -import dagger.Provides @Module interface QSHostModule { @@ -37,36 +34,10 @@ interface QSHostModule { @Binds fun provideEventLogger(impl: QsEventLoggerImpl): QsEventLogger - @Module - companion object { - private const val MAX_QS_INSTANCE_ID = 1 shl 20 + @Binds fun providePanelInteractor(impl: PanelInteractorImpl): PanelInteractor - @Provides - @JvmStatic - fun providePanelInteractor( - featureFlags: QSPipelineFlagsRepository, - qsHost: QSTileHost, - panelInteractorImpl: PanelInteractorImpl - ): PanelInteractor { - return if (featureFlags.pipelineEnabled) { - panelInteractorImpl - } else { - qsHost - } - } - - @Provides - @JvmStatic - fun provideCustomTileAddedRepository( - featureFlags: QSPipelineFlagsRepository, - qsHost: QSTileHost, - customTileAddedRepository: CustomTileAddedSharedPrefsRepository - ): CustomTileAddedRepository { - return if (featureFlags.pipelineEnabled) { - customTileAddedRepository - } else { - qsHost - } - } - } + @Binds + fun provideCustomTileAddedRepository( + impl: CustomTileAddedSharedPrefsRepository + ): CustomTileAddedRepository } diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java index b705a0389300..29bcad4e0e0c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java @@ -16,17 +16,7 @@ package com.android.systemui.qs.dagger; -import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE; - -import android.content.Context; -import android.os.Handler; - -import com.android.systemui.dagger.NightDisplayListenerModule; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.media.dagger.MediaModule; -import com.android.systemui.qs.AutoAddTracker; -import com.android.systemui.qs.QSHost; import com.android.systemui.qs.ReduceBrightColorsController; import com.android.systemui.qs.ReduceBrightColorsControllerImpl; import com.android.systemui.qs.external.QSExternalModule; @@ -36,25 +26,13 @@ import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.qs.tiles.di.QSTilesModule; import com.android.systemui.qs.ui.adapter.QSSceneAdapter; import com.android.systemui.qs.ui.adapter.QSSceneAdapterImpl; -import com.android.systemui.statusbar.phone.AutoTileManager; -import com.android.systemui.statusbar.phone.ManagedProfileController; -import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.DeviceControlsController; -import com.android.systemui.statusbar.policy.HotspotController; -import com.android.systemui.statusbar.policy.SafetyController; -import com.android.systemui.statusbar.policy.WalletController; -import com.android.systemui.util.settings.SecureSettings; + +import java.util.Map; import dagger.Binds; import dagger.Module; -import dagger.Provides; import dagger.multibindings.Multibinds; -import java.util.Map; - -import javax.inject.Named; - /** * Module for QS dependencies */ @@ -78,45 +56,6 @@ public interface QSModule { @Multibinds Map<String, QSTileImpl<?>> tileMap(); - @Provides - @SysUISingleton - static AutoTileManager provideAutoTileManager( - Context context, - AutoAddTracker.Builder autoAddTrackerBuilder, - QSHost host, - @Background Handler handler, - SecureSettings secureSettings, - HotspotController hotspotController, - DataSaverController dataSaverController, - ManagedProfileController managedProfileController, - NightDisplayListenerModule.Builder nightDisplayListenerBuilder, - CastController castController, - ReduceBrightColorsController reduceBrightColorsController, - DeviceControlsController deviceControlsController, - WalletController walletController, - SafetyController safetyController, - @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { - AutoTileManager manager = new AutoTileManager( - context, - autoAddTrackerBuilder, - host, - handler, - secureSettings, - hotspotController, - dataSaverController, - managedProfileController, - nightDisplayListenerBuilder, - castController, - reduceBrightColorsController, - deviceControlsController, - walletController, - safetyController, - isReduceBrightColorsAvailable - ); - manager.init(); - return manager; - } - @Binds QSSceneAdapter bindsQsSceneInteractor(QSSceneAdapterImpl impl); diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt index ba45d172b082..6dc101a63f09 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt @@ -21,6 +21,7 @@ import android.util.Log import android.view.ContextThemeWrapper import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleOwner import com.android.settingslib.Utils import com.android.systemui.animation.Expandable @@ -41,6 +42,7 @@ import javax.inject.Inject import javax.inject.Named import javax.inject.Provider import kotlin.math.max +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -48,6 +50,8 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch private const val TAG = "FooterActionsViewModel" @@ -140,6 +144,30 @@ class FooterActionsViewModel( showPowerButton, ) } + + fun create(lifecycleCoroutineScope: LifecycleCoroutineScope): FooterActionsViewModel { + val globalActionsDialogLite = globalActionsDialogLiteProvider.get() + if (lifecycleCoroutineScope.isActive) { + lifecycleCoroutineScope.launch { + try { + awaitCancellation() + } finally { + globalActionsDialogLite.destroy() + } + } + } else { + globalActionsDialogLite.destroy() + } + + return FooterActionsViewModel( + context, + footerActionsInteractor, + falsingManager, + globalActionsDialogLite, + activityStarter, + showPowerButton, + ) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt index 2c578130e920..0b9cd96670b1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt @@ -20,103 +20,40 @@ import android.content.ClipData import androidx.compose.foundation.draganddrop.dragAndDropSource import androidx.compose.foundation.draganddrop.dragAndDropTarget import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.lazy.grid.LazyGridItemInfo +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.draganddrop.DragAndDropEvent import androidx.compose.ui.draganddrop.DragAndDropTarget import androidx.compose.ui.draganddrop.DragAndDropTransferData import androidx.compose.ui.draganddrop.mimeTypes +import androidx.compose.ui.draganddrop.toAndroidDragEvent +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.center +import androidx.compose.ui.unit.toRect import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.pipeline.shared.TileSpec -@Composable -fun rememberDragAndDropState(listState: EditTileListState): DragAndDropState { - val draggedCell: MutableState<SizedTile<EditTileViewModel>?> = remember { mutableStateOf(null) } - return remember(listState) { DragAndDropState(draggedCell, listState) } -} - -/** - * Holds the [TileSpec] of the tile being moved and modify the [EditTileListState] based on drag and - * drop events. - */ -class DragAndDropState( - val draggedCell: MutableState<SizedTile<EditTileViewModel>?>, - private val listState: EditTileListState, -) { +/** Holds the [TileSpec] of the tile being moved and receives drag and drop events. */ +interface DragAndDropState { + val draggedCell: SizedTile<EditTileViewModel>? val dragInProgress: Boolean - get() = draggedCell.value != null - - /** Returns index of the dragged tile if it's present in the list. Returns -1 if not. */ - fun currentPosition(): Int { - return draggedCell.value?.let { listState.indexOf(it.tile.tileSpec) } ?: -1 - } - - fun isMoving(tileSpec: TileSpec): Boolean { - return draggedCell.value?.let { it.tile.tileSpec == tileSpec } ?: false - } - fun onStarted(cell: SizedTile<EditTileViewModel>) { - draggedCell.value = cell - } + fun isMoving(tileSpec: TileSpec): Boolean - fun onMoved(targetSpec: TileSpec) { - draggedCell.value?.let { listState.move(it, targetSpec) } - } + fun onStarted(cell: SizedTile<EditTileViewModel>) - fun movedOutOfBounds() { - // Removing the tiles from the current tile grid if it moves out of bounds. This clears - // the spacer and makes it apparent that dropping the tile at that point would remove it. - draggedCell.value?.let { listState.remove(it.tile.tileSpec) } - } + fun onMoved(target: Int, insertAfter: Boolean) - fun onDrop() { - draggedCell.value = null - } -} - -/** - * Registers a tile as a [DragAndDropTarget] to receive drag events and update the - * [DragAndDropState] with the tile's position, which can be used to insert a temporary placeholder. - * - * @param dragAndDropState The [DragAndDropState] using the tiles list - * @param tileSpec The [TileSpec] of the tile - * @param acceptDrops Whether the tile should accept a drop based on a given [TileSpec] - * @param onDrop Action to be executed when a [TileSpec] is dropped on the tile - */ -@Composable -fun Modifier.dragAndDropTile( - dragAndDropState: DragAndDropState, - tileSpec: TileSpec, - acceptDrops: (TileSpec) -> Boolean, - onDrop: (TileSpec, Int) -> Unit, -): Modifier { - val target = - remember(dragAndDropState) { - object : DragAndDropTarget { - override fun onDrop(event: DragAndDropEvent): Boolean { - return dragAndDropState.draggedCell.value?.let { - onDrop(it.tile.tileSpec, dragAndDropState.currentPosition()) - dragAndDropState.onDrop() - true - } ?: false - } + fun movedOutOfBounds() - override fun onEntered(event: DragAndDropEvent) { - dragAndDropState.onMoved(tileSpec) - } - } - } - return dragAndDropTarget( - shouldStartDragAndDrop = { event -> - event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE) && - dragAndDropState.draggedCell.value?.let { acceptDrops(it.tile.tileSpec) } ?: false - }, - target = target, - ) + fun onDrop() } /** @@ -135,7 +72,7 @@ fun Modifier.dragAndDropRemoveZone( remember(dragAndDropState) { object : DragAndDropTarget { override fun onDrop(event: DragAndDropEvent): Boolean { - return dragAndDropState.draggedCell.value?.let { + return dragAndDropState.draggedCell?.let { onDrop(it.tile.tileSpec) dragAndDropState.onDrop() true @@ -156,19 +93,22 @@ fun Modifier.dragAndDropRemoveZone( } /** - * Registers a tile list as a [DragAndDropTarget] to receive drop events. Use this on list - * containers to catch drops outside of tiles. + * Registers a tile list as a [DragAndDropTarget] to receive drop events. Use this on the lazy tile + * grid to receive drag and drops events. * + * @param gridState The [LazyGridState] of the tile list + * @param contentOffset The [Offset] of the tile list * @param dragAndDropState The [DragAndDropState] using the tiles list - * @param acceptDrops Whether the tile should accept a drop based on a given [TileSpec] - * @param onDrop Action to be executed when a [TileSpec] is dropped on the tile + * @param onDrop Callback when a tile is dropped */ @Composable fun Modifier.dragAndDropTileList( + gridState: LazyGridState, + contentOffset: Offset, dragAndDropState: DragAndDropState, - acceptDrops: (TileSpec) -> Boolean, - onDrop: (TileSpec, Int) -> Unit, + onDrop: () -> Unit, ): Modifier { + val currentContentOffset by rememberUpdatedState(contentOffset) val target = remember(dragAndDropState) { object : DragAndDropTarget { @@ -176,9 +116,23 @@ fun Modifier.dragAndDropTileList( dragAndDropState.onDrop() } + override fun onMoved(event: DragAndDropEvent) { + // Drag offset relative to the list's top left corner + val relativeDragOffset = event.dragOffsetRelativeTo(currentContentOffset) + val targetItem = + gridState.layoutInfo.visibleItemsInfo.firstOrNull { item -> + // Check if the drag is on this item + IntRect(item.offset, item.size).toRect().contains(relativeDragOffset) + } + + targetItem?.let { + dragAndDropState.onMoved(it.index, insertAfter(it, relativeDragOffset)) + } + } + override fun onDrop(event: DragAndDropEvent): Boolean { - return dragAndDropState.draggedCell.value?.let { - onDrop(it.tile.tileSpec, dragAndDropState.currentPosition()) + return dragAndDropState.draggedCell?.let { + onDrop() dragAndDropState.onDrop() true } ?: false @@ -188,12 +142,22 @@ fun Modifier.dragAndDropTileList( return dragAndDropTarget( target = target, shouldStartDragAndDrop = { event -> - event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE) && - dragAndDropState.draggedCell.value?.let { acceptDrops(it.tile.tileSpec) } ?: false + event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE) }, ) } +private fun DragAndDropEvent.dragOffsetRelativeTo(offset: Offset): Offset { + return toAndroidDragEvent().run { Offset(x, y) } - offset +} + +private fun insertAfter(item: LazyGridItemInfo, offset: Offset): Boolean { + // We want to insert the tile after the target if we're aiming at the right side of a large tile + // TODO(ostonge): Verify this behavior in RTL + val itemCenter = item.offset + item.size.center + return item.span != 1 && offset.x > itemCenter.x +} + fun Modifier.dragAndDropTileSource( sizedTile: SizedTile<EditTileViewModel>, onTap: (TileSpec) -> Unit, diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt index 3bda7757f8e5..1674865bcce6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt @@ -43,6 +43,7 @@ fun EditMode( Modifier, viewModel::addTile, viewModel::removeTile, + viewModel::setTiles, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt index fa3008e3f292..4830ba7baa9b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt @@ -17,46 +17,106 @@ package com.android.systemui.qs.panels.ui.compose import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.toMutableStateList import com.android.systemui.qs.panels.shared.model.SizedTile +import com.android.systemui.qs.panels.ui.model.GridCell +import com.android.systemui.qs.panels.ui.model.TileGridCell +import com.android.systemui.qs.panels.ui.model.toGridCells import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.pipeline.shared.TileSpec +/** + * Creates the edit tile list state that is remembered across compositions. + * + * Changes to the tiles or columns will recreate the state. + */ @Composable fun rememberEditListState( tiles: List<SizedTile<EditTileViewModel>>, + columns: Int, ): EditTileListState { - return remember(tiles) { EditTileListState(tiles) } + return remember(tiles, columns) { EditTileListState(tiles, columns) } } /** Holds the temporary state of the tile list during a drag movement where we move tiles around. */ -class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>) { - val tiles: SnapshotStateList<SizedTile<EditTileViewModel>> = tiles.toMutableStateList() +class EditTileListState( + tiles: List<SizedTile<EditTileViewModel>>, + private val columns: Int, +) : DragAndDropState { + private val _draggedCell = mutableStateOf<SizedTile<EditTileViewModel>?>(null) + override val draggedCell + get() = _draggedCell.value + + override val dragInProgress: Boolean + get() = _draggedCell.value != null + + private val _tiles: SnapshotStateList<GridCell> = + tiles.toGridCells(columns).toMutableStateList() + val tiles: List<GridCell> + get() = _tiles.toList() + + fun tileSpecs(): List<TileSpec> { + return _tiles.filterIsInstance<TileGridCell>().map { it.tile.tileSpec } + } + + fun indexOf(tileSpec: TileSpec): Int { + return _tiles.indexOfFirst { it is TileGridCell && it.tile.tileSpec == tileSpec } + } + + override fun isMoving(tileSpec: TileSpec): Boolean { + return _draggedCell.value?.let { it.tile.tileSpec == tileSpec } ?: false + } - fun move(sizedTile: SizedTile<EditTileViewModel>, target: TileSpec) { - val fromIndex = indexOf(sizedTile.tile.tileSpec) - val toIndex = indexOf(target) + override fun onStarted(cell: SizedTile<EditTileViewModel>) { + _draggedCell.value = cell - if (toIndex == -1 || fromIndex == toIndex) { + // Add visible spacers to the grid to indicate where the user can move a tile + regenerateGrid(includeSpacers = true) + } + + override fun onMoved(target: Int, insertAfter: Boolean) { + val draggedTile = _draggedCell.value ?: return + + val fromIndex = indexOf(draggedTile.tile.tileSpec) + if (fromIndex == target) { return } - if (fromIndex == -1) { - // If tile isn't in the list, simply insert it - tiles.add(toIndex, sizedTile) + val insertionIndex = if (insertAfter) target + 1 else target + if (fromIndex != -1) { + val cell = _tiles.removeAt(fromIndex) + regenerateGrid(includeSpacers = true) + _tiles.add(insertionIndex.coerceIn(0, _tiles.size), cell) } else { - // If tile is present in the list, move it - tiles.apply { add(toIndex, removeAt(fromIndex)) } + // Add the tile with a temporary row which will get reassigned when regenerating spacers + _tiles.add(insertionIndex.coerceIn(0, _tiles.size), TileGridCell(draggedTile, 0)) } + + regenerateGrid(includeSpacers = true) } - fun remove(tileSpec: TileSpec) { - tiles.removeIf { it.tile.tileSpec == tileSpec } + override fun movedOutOfBounds() { + val draggedTile = _draggedCell.value ?: return + + _tiles.removeIf { cell -> + cell is TileGridCell && cell.tile.tileSpec == draggedTile.tile.tileSpec + } } - fun indexOf(tileSpec: TileSpec): Int { - return tiles.indexOfFirst { it.tile.tileSpec == tileSpec } + override fun onDrop() { + _draggedCell.value = null + + // Remove the spacers + regenerateGrid(includeSpacers = false) + } + + private fun regenerateGrid(includeSpacers: Boolean) { + _tiles.filterIsInstance<TileGridCell>().toGridCells(columns, includeSpacers).let { + _tiles.clear() + _tiles.addAll(it) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt index e2f6bcf2e872..fd276c2dd220 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt @@ -39,6 +39,7 @@ interface GridLayout { modifier: Modifier, onAddTile: (TileSpec, Int) -> Unit, onRemoveTile: (TileSpec) -> Unit, + onSetTiles: (List<TileSpec>) -> Unit, ) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt index bd925fee2800..d948dfd7d3b9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt @@ -76,6 +76,7 @@ constructor( modifier: Modifier, onAddTile: (TileSpec, Int) -> Unit, onRemoveTile: (TileSpec) -> Unit, + onSetTiles: (List<TileSpec>) -> Unit, ) { val columns by gridSizeViewModel.columns.collectAsStateWithLifecycle() val largeTiles by iconTilesViewModel.largeTiles.collectAsStateWithLifecycle() @@ -91,12 +92,16 @@ constructor( } } + val (currentTiles, otherTiles) = sizedTiles.partition { it.tile.isCurrent } + val currentListState = rememberEditListState(currentTiles, columns) DefaultEditTileGrid( - sizedTiles = sizedTiles, + currentListState = currentListState, + otherTiles = otherTiles, columns = columns, modifier = modifier, onAddTile = onAddTile, onRemoveTile = onRemoveTile, + onSetTiles = onSetTiles, onResize = iconTilesViewModel::resize, ) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt index 2ee957e89f48..08a56bf29f66 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.qs.panels.dagger.PaginatedBaseLayoutType import com.android.systemui.qs.panels.ui.compose.PaginatedGridLayout.Dimensions.FooterHeight import com.android.systemui.qs.panels.ui.compose.PaginatedGridLayout.Dimensions.InterPageSpacing @@ -77,7 +78,7 @@ constructor( Column { HorizontalPager( state = pagerState, - modifier = Modifier, + modifier = Modifier.sysuiResTag("qs_pager"), pageSpacing = if (pages.size > 1) InterPageSpacing else 0.dp, beyondViewportPageCount = 1, verticalAlignment = Alignment.Top, diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt index af3803b6ff34..a9027ff92996 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.qs.panels.ui.viewmodel.QuickQuickSettingsViewModel import com.android.systemui.res.R @@ -44,7 +45,10 @@ fun QuickQuickSettings( } val columns by viewModel.columns.collectAsStateWithLifecycle() - TileLazyGrid(modifier = modifier, columns = GridCells.Fixed(columns)) { + TileLazyGrid( + modifier = modifier.sysuiResTag("qqs_tile_layout"), + columns = GridCells.Fixed(columns) + ) { items( tiles.size, key = { index -> sizedTiles[index].tile.spec.spec }, diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt index 7e6ccd635a96..c06d6d2dc957 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt @@ -22,7 +22,6 @@ import android.graphics.drawable.Animatable import android.service.quicksettings.Tile.STATE_ACTIVE import android.service.quicksettings.Tile.STATE_INACTIVE import android.text.TextUtils -import androidx.appcompat.content.res.AppCompatResources import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn @@ -53,8 +52,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridItemScope import androidx.compose.foundation.lazy.grid.LazyGridScope +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -76,9 +78,13 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.onClick @@ -90,6 +96,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.Expandable +import com.android.compose.modifiers.background import com.android.compose.modifiers.thenIf import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon @@ -97,8 +104,10 @@ import com.android.systemui.common.ui.compose.Icon import com.android.systemui.common.ui.compose.load import com.android.systemui.plugins.qs.QSTile import com.android.systemui.qs.panels.shared.model.SizedTile +import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.model.GridCell +import com.android.systemui.qs.panels.ui.model.SpacerGridCell import com.android.systemui.qs.panels.ui.model.TileGridCell -import com.android.systemui.qs.panels.ui.model.toTileGridCells import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel import com.android.systemui.qs.panels.ui.viewmodel.toUiState @@ -270,10 +279,12 @@ private fun Modifier.tileMarquee(): Modifier { @Composable fun TileLazyGrid( modifier: Modifier = Modifier, + state: LazyGridState = rememberLazyGridState(), columns: GridCells, content: LazyGridScope.() -> Unit, ) { LazyVerticalGrid( + state = state, columns = columns, verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)), horizontalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_horizontal)), @@ -284,23 +295,18 @@ fun TileLazyGrid( @Composable fun DefaultEditTileGrid( - sizedTiles: List<SizedTile<EditTileViewModel>>, + currentListState: EditTileListState, + otherTiles: List<SizedTile<EditTileViewModel>>, columns: Int, modifier: Modifier, onAddTile: (TileSpec, Int) -> Unit, onRemoveTile: (TileSpec) -> Unit, + onSetTiles: (List<TileSpec>) -> Unit, onResize: (TileSpec) -> Unit, ) { - val (currentTiles, otherTiles) = sizedTiles.partition { it.tile.isCurrent } - val currentListState = rememberEditListState(currentTiles) - val dragAndDropState = rememberDragAndDropState(currentListState) - val addTileToEnd: (TileSpec) -> Unit by rememberUpdatedState { onAddTile(it, CurrentTilesInteractor.POSITION_AT_END) } - val onDropAdd: (TileSpec, Int) -> Unit by rememberUpdatedState { tileSpec, position -> - onAddTile(tileSpec, position) - } val tilePadding = dimensionResource(R.dimen.qs_tile_margin_vertical) CompositionLocalProvider(LocalOverscrollConfiguration provides null) { @@ -310,10 +316,10 @@ fun DefaultEditTileGrid( modifier = modifier.fillMaxSize().verticalScroll(rememberScrollState()) ) { AnimatedContent( - targetState = dragAndDropState.dragInProgress, + targetState = currentListState.dragInProgress, modifier = Modifier.wrapContentSize() ) { dragIsInProgress -> - EditGridHeader(Modifier.dragAndDropRemoveZone(dragAndDropState, onRemoveTile)) { + EditGridHeader(Modifier.dragAndDropRemoveZone(currentListState, onRemoveTile)) { if (dragIsInProgress) { RemoveTileTarget() } else { @@ -323,18 +329,17 @@ fun DefaultEditTileGrid( } CurrentTilesGrid( - currentListState.tiles, + currentListState, columns, tilePadding, onRemoveTile, onResize, - dragAndDropState, - onDropAdd, + onSetTiles, ) // Hide available tiles when dragging AnimatedVisibility( - visible = !dragAndDropState.dragInProgress, + visible = !currentListState.dragInProgress, enter = fadeIn(), exit = fadeOut() ) { @@ -350,7 +355,7 @@ fun DefaultEditTileGrid( columns, tilePadding, addTileToEnd, - dragAndDropState, + currentListState, ) } } @@ -360,7 +365,7 @@ fun DefaultEditTileGrid( modifier = Modifier.fillMaxWidth() .weight(1f) - .dragAndDropRemoveZone(dragAndDropState, onRemoveTile) + .dragAndDropRemoveZone(currentListState, onRemoveTile) ) } } @@ -376,7 +381,7 @@ private fun EditGridHeader( ) { Box( contentAlignment = Alignment.Center, - modifier = modifier.fillMaxWidth().height(TileDefaults.EditGridHeaderHeight) + modifier = modifier.fillMaxWidth().height(EditModeTileDefaults.EditGridHeaderHeight) ) { content() } @@ -415,35 +420,42 @@ private fun CurrentTilesContainer(content: @Composable () -> Unit) { @Composable private fun CurrentTilesGrid( - tiles: List<SizedTile<EditTileViewModel>>, + listState: EditTileListState, columns: Int, tilePadding: Dp, onClick: (TileSpec) -> Unit, onResize: (TileSpec) -> Unit, - dragAndDropState: DragAndDropState, - onDrop: (TileSpec, Int) -> Unit + onSetTiles: (List<TileSpec>) -> Unit, ) { - // Current tiles + val currentListState by rememberUpdatedState(listState) + CurrentTilesContainer { - val cells = tiles.toTileGridCells(columns) val tileHeight = tileHeight() - val totalRows = cells.lastOrNull()?.row ?: 0 + val totalRows = listState.tiles.lastOrNull()?.row ?: 0 val totalHeight = gridHeight(totalRows + 1, tileHeight, tilePadding) + val gridState = rememberLazyGridState() + var gridContentOffset by remember { mutableStateOf(Offset(0f, 0f)) } + TileLazyGrid( + state = gridState, modifier = Modifier.height(totalHeight) - .dragAndDropTileList(dragAndDropState, { true }, onDrop), + .dragAndDropTileList(gridState, gridContentOffset, listState) { + onSetTiles(currentListState.tileSpecs()) + } + .onGloballyPositioned { coordinates -> + gridContentOffset = coordinates.positionInRoot() + } + .testTag(CURRENT_TILES_GRID_TEST_TAG), columns = GridCells.Fixed(columns) ) { editTiles( - cells, + listState.tiles, ClickAction.REMOVE, onClick, - dragAndDropState, + listState, onResize = onResize, indicatePosition = true, - acceptDrops = { true }, - onDrop = onDrop, ) } } @@ -465,7 +477,7 @@ private fun AvailableTileGrid( // Available tiles TileLazyGrid( - modifier = Modifier.height(availableGridHeight), + modifier = Modifier.height(availableGridHeight).testTag(AVAILABLE_TILES_GRID_TEST_TAG), columns = GridCells.Fixed(columns) ) { editTiles( @@ -473,7 +485,6 @@ private fun AvailableTileGrid( ClickAction.ADD, onClick, dragAndDropState = dragAndDropState, - acceptDrops = { false }, showLabels = true, ) editTiles( @@ -481,7 +492,6 @@ private fun AvailableTileGrid( ClickAction.ADD, onClick, dragAndDropState = dragAndDropState, - acceptDrops = { false }, showLabels = true, ) } @@ -496,64 +506,109 @@ fun gridHeight(rows: Int, tileHeight: Dp, padding: Dp): Dp { return ((tileHeight + padding) * rows) - padding } +private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any { + return if (this is TileGridCell && !dragAndDropState.isMoving(tile.tileSpec)) { + key + } else { + index + } +} + fun LazyGridScope.editTiles( - cells: List<TileGridCell>, + cells: List<GridCell>, clickAction: ClickAction, onClick: (TileSpec) -> Unit, dragAndDropState: DragAndDropState, - acceptDrops: (TileSpec) -> Boolean, onResize: (TileSpec) -> Unit = {}, - onDrop: (TileSpec, Int) -> Unit = { _, _ -> }, showLabels: Boolean = false, indicatePosition: Boolean = false, ) { items( count = cells.size, - key = { cells[it].key }, + key = { cells[it].key(it, dragAndDropState) }, span = { cells[it].span }, contentType = { TileType } ) { index -> - val cell = cells[index] - val tileHeight = tileHeight(cell.isIcon && showLabels) - - if (!dragAndDropState.isMoving(cell.tile.tileSpec)) { - val onClickActionName = - when (clickAction) { - ClickAction.ADD -> - stringResource(id = R.string.accessibility_qs_edit_tile_add_action) - ClickAction.REMOVE -> - stringResource(id = R.string.accessibility_qs_edit_remove_tile_action) - } - val stateDescription = - if (indicatePosition) { - stringResource(id = R.string.accessibility_qs_edit_position, index + 1) + when (val cell = cells[index]) { + is TileGridCell -> + if (dragAndDropState.isMoving(cell.tile.tileSpec)) { + // If the tile is being moved, replace it with a visible spacer + SpacerGridCell( + Modifier.background( + color = MaterialTheme.colorScheme.secondary, + alpha = { EditModeTileDefaults.PLACEHOLDER_ALPHA }, + shape = TileDefaults.TileShape + ) + .animateItem() + ) } else { - "" + TileGridCell( + cell = cell, + index = index, + dragAndDropState = dragAndDropState, + clickAction = clickAction, + onClick = onClick, + onResize = onResize, + showLabels = showLabels, + indicatePosition = indicatePosition + ) } - EditTile( - tileViewModel = cell.tile, - iconOnly = cell.isIcon, - showLabels = showLabels, - modifier = - Modifier.height(tileHeight) - .animateItem() - .semantics { - onClick(onClickActionName) { false } - this.stateDescription = stateDescription - } - .dragAndDropTile(dragAndDropState, cell.tile.tileSpec, acceptDrops, onDrop) - .dragAndDropTileSource( - cell, - onClick, - onResize, - dragAndDropState, - ) - ) + is SpacerGridCell -> SpacerGridCell() } } } @Composable +private fun LazyGridItemScope.TileGridCell( + cell: TileGridCell, + index: Int, + dragAndDropState: DragAndDropState, + clickAction: ClickAction, + onClick: (TileSpec) -> Unit, + onResize: (TileSpec) -> Unit = {}, + showLabels: Boolean = false, + indicatePosition: Boolean = false, +) { + val tileHeight = tileHeight(cell.isIcon && showLabels) + val onClickActionName = + when (clickAction) { + ClickAction.ADD -> stringResource(id = R.string.accessibility_qs_edit_tile_add_action) + ClickAction.REMOVE -> + stringResource(id = R.string.accessibility_qs_edit_remove_tile_action) + } + val stateDescription = + if (indicatePosition) { + stringResource(id = R.string.accessibility_qs_edit_position, index + 1) + } else { + "" + } + EditTile( + tileViewModel = cell.tile, + iconOnly = cell.isIcon, + showLabels = showLabels, + modifier = + Modifier.height(tileHeight) + .animateItem() + .semantics { + onClick(onClickActionName) { false } + this.stateDescription = stateDescription + } + .dragAndDropTileSource( + SizedTileImpl(cell.tile, cell.width), + onClick, + onResize, + dragAndDropState, + ) + ) +} + +@Composable +private fun SpacerGridCell(modifier: Modifier = Modifier) { + // By default, spacers are invisible and exist purely to catch drag movements + Box(modifier.height(tileHeight()).fillMaxWidth().tilePadding()) +} + +@Composable fun EditTile( tileViewModel: EditTileViewModel, iconOnly: Boolean, @@ -593,15 +648,15 @@ enum class ClickAction { } @Composable -private fun getTileIcon(icon: Supplier<QSTile.Icon>): Icon { +private fun getTileIcon(icon: Supplier<QSTile.Icon?>): Icon { val context = LocalContext.current - return icon.get().let { + return icon.get()?.let { if (it is QSTileImpl.ResourceIcon) { Icon.Resource(it.resId, null) } else { Icon.Loaded(it.getDrawable(context), null) } - } + } ?: Icon.Resource(R.drawable.ic_error_outline, null) } @OptIn(ExperimentalAnimationGraphicsApi::class) @@ -618,7 +673,7 @@ private fun TileIcon( remember(icon, context) { when (icon) { is Icon.Loaded -> icon.drawable - is Icon.Resource -> AppCompatResources.getDrawable(context, icon.res) + is Icon.Resource -> context.getDrawable(icon.res) } } if (loadedDrawable !is Animatable) { @@ -642,7 +697,7 @@ private fun TileIcon( } Image( painter = painter, - contentDescription = null, + contentDescription = icon.contentDescription?.load(), colorFilter = ColorFilter.tint(color = color), modifier = iconModifier ) @@ -679,10 +734,14 @@ private data class TileColors( val icon: Color, ) +private object EditModeTileDefaults { + const val PLACEHOLDER_ALPHA = .3f + val EditGridHeaderHeight = 60.dp +} + private object TileDefaults { val TileShape = CircleShape val IconTileWithLabelHeight = 140.dp - val EditGridHeaderHeight = 60.dp @Composable fun activeTileColors(): TileColors = @@ -723,3 +782,6 @@ private object TileDefaults { } } } + +private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid" +private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid" diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt index c241fd87d9d5..8ca8de762772 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt @@ -22,6 +22,12 @@ import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.shared.model.splitInRowsSequence import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel +/** Represents an item from a grid associated with a row and a span */ +interface GridCell { + val row: Int + val span: GridItemSpan +} + /** * Represents a [EditTileViewModel] from a grid associated with a tile format and the row it's * positioned at @@ -29,10 +35,12 @@ import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel @Immutable data class TileGridCell( override val tile: EditTileViewModel, - val row: Int, - val key: String = "${tile.tileSpec.spec}-$row", + override val row: Int, override val width: Int, -) : SizedTile<EditTileViewModel> { + override val span: GridItemSpan = GridItemSpan(width) +) : GridCell, SizedTile<EditTileViewModel> { + val key: String = "${tile.tileSpec.spec}-$row" + constructor( sizedTile: SizedTile<EditTileViewModel>, row: Int @@ -41,12 +49,30 @@ data class TileGridCell( row = row, width = sizedTile.width, ) - - val span = GridItemSpan(width) } -fun List<SizedTile<EditTileViewModel>>.toTileGridCells(columns: Int): List<TileGridCell> { +/** Represents an empty space used to fill incomplete rows. Will always display as a 1x1 tile */ +@Immutable +data class SpacerGridCell( + override val row: Int, + override val span: GridItemSpan = GridItemSpan(1) +) : GridCell + +fun List<SizedTile<EditTileViewModel>>.toGridCells( + columns: Int, + includeSpacers: Boolean = false +): List<GridCell> { return splitInRowsSequence(this, columns) - .flatMapIndexed { index, sizedTiles -> sizedTiles.map { TileGridCell(it, index) } } + .flatMapIndexed { rowIndex, sizedTiles -> + val row: List<GridCell> = sizedTiles.map { TileGridCell(it, rowIndex) } + + if (includeSpacers) { + // Fill the incomplete rows with spacers + val numSpacers = columns - sizedTiles.sumOf { it.width } + row.toMutableList().apply { repeat(numSpacers) { add(SpacerGridCell(rowIndex)) } } + } else { + row + } + } .toList() } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt index ef2c8bfe0e4c..42715be6f6c0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt @@ -179,6 +179,10 @@ constructor( currentTilesInteractor.removeTiles(listOf(tileSpec)) } + fun setTiles(tileSpecs: List<TileSpec>) { + currentTilesInteractor.setTiles(tileSpecs) + } + /** Immediately resets the current tiles to the default list. */ fun resetCurrentTilesToDefault() { throw NotImplementedError("This is not supported yet") diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt index 4ec59c969a59..c83e3b2a0e06 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt @@ -25,7 +25,7 @@ data class TileUiState( val label: String, val secondaryLabel: String, val state: Int, - val icon: Supplier<QSTile.Icon>, + val icon: Supplier<QSTile.Icon?>, ) fun QSTile.State.toUiState(): TileUiState { @@ -33,6 +33,6 @@ fun QSTile.State.toUiState(): TileUiState { label?.toString() ?: "", secondaryLabel?.toString() ?: "", state, - icon?.let { Supplier { icon } } ?: iconSupplier, + icon?.let { Supplier { icon } } ?: iconSupplier ?: Supplier { null }, ) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt index 02379e6efecc..4a96710f083c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt @@ -116,6 +116,8 @@ interface CurrentTilesInteractor : ProtoDumpable { */ fun setTiles(specs: List<TileSpec>) + fun createTileSync(spec: TileSpec): QSTile? + companion object { val POSITION_AT_END: Int = TileSpecRepository.POSITION_AT_END } @@ -190,9 +192,7 @@ constructor( } init { - if (featureFlags.pipelineEnabled) { - startTileCollection() - } + startTileCollection() } private fun startTileCollection() { @@ -342,15 +342,16 @@ constructor( lifecycleManager.flushMessagesAndUnbind() } + override fun createTileSync(spec: TileSpec): QSTile? { + return if (featureFlags.tilesEnabled) { + newQSTileFactory.get().createTile(spec.spec) + } else { + null + } ?: tileFactory.createTile(spec.spec) + } + private suspend fun createTile(spec: TileSpec): QSTile? { - val tile = - withContext(mainDispatcher) { - if (featureFlags.tilesEnabled) { - newQSTileFactory.get().createTile(spec.spec) - } else { - null - } ?: tileFactory.createTile(spec.spec) - } + val tile = withContext(mainDispatcher) { createTileSync(spec) } if (tile == null) { logger.logTileNotFoundInFactory(spec) return null diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt index c8fbeb50b039..0bcb6b7e7874 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt @@ -40,14 +40,12 @@ constructor( ) : CoreStartable { override fun start() { - if (featureFlags.pipelineEnabled) { - accessibilityTilesInteractor.init(currentTilesInteractor) - autoAddInteractor.init(currentTilesInteractor) - restoreReconciliationInteractor.start() + accessibilityTilesInteractor.init(currentTilesInteractor) + autoAddInteractor.init(currentTilesInteractor) + restoreReconciliationInteractor.start() - if (NewQsUI.isEnabled) { - gridConsistencyInteractor.start() - } + if (NewQsUI.isEnabled) { + gridConsistencyInteractor.start() } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt index 42bee3c8f877..5dc8d1bd4643 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt @@ -9,19 +9,10 @@ import javax.inject.Inject @SysUISingleton class QSPipelineFlagsRepository @Inject constructor() { - val pipelineEnabled: Boolean - get() = AconfigFlags.qsNewPipeline() - val tilesEnabled: Boolean get() = AconfigFlags.qsNewTiles() companion object Utils { - fun assertInLegacyMode() = - RefactorFlagUtils.assertInLegacyMode( - AconfigFlags.qsNewPipeline(), - AconfigFlags.FLAG_QS_NEW_PIPELINE - ) - fun assertNewTiles() = RefactorFlagUtils.assertInNewMode( AconfigFlags.qsNewTiles(), diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt index 2a33a16fa43a..5f10b385e23b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt @@ -20,6 +20,7 @@ import android.app.Flags import android.content.Intent import android.os.Handler import android.os.Looper +import android.service.quicksettings.Tile import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import androidx.lifecycle.repeatOnLifecycle @@ -94,7 +95,13 @@ constructor( override fun getTileLabel(): CharSequence = tileState.label - override fun newTileState() = QSTile.State() + override fun newTileState(): QSTile.State { + return QSTile.State().apply { + label = mContext.getString(R.string.quick_settings_modes_label) + icon = ResourceIcon.get(R.drawable.qs_dnd_icon_off) + state = Tile.STATE_INACTIVE + } + } override fun handleClick(expandable: Expandable?) = runBlocking { userActionInteractor.handleClick(expandable) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index b2873c5662e7..5ea9e6ae0a70 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -346,7 +346,6 @@ public class InternetDialogController implements AccessPointController.AccessPoi mCallback = null; } - @VisibleForTesting boolean isAirplaneModeEnabled() { return mGlobalSettings.getInt(Settings.Global.AIRPLANE_MODE_ON, 0) != 0; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java index f0183360bea9..71f8639c1e22 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java @@ -30,7 +30,6 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionManager; import android.telephony.TelephonyDisplayInfo; -import android.telephony.TelephonyManager; import android.text.Html; import android.text.Layout; import android.text.TextUtils; @@ -50,9 +49,14 @@ import android.widget.Switch; import android.widget.TextView; import androidx.annotation.MainThread; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleRegistry; +import androidx.lifecycle.MutableLiveData; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -110,7 +114,6 @@ public class InternetDialogDelegate implements protected boolean mCanConfigWifi; private final InternetDialogManager mInternetDialogManager; - private TelephonyManager mTelephonyManager; @Nullable private AlertDialog mAlertDialog; private final UiEventLogger mUiEventLogger; @@ -169,6 +172,13 @@ public class InternetDialogDelegate implements @Nullable private Job mClickJob; + // These are to reduce the UI janky frame duration. b/323286540 + private LifecycleRegistry mLifecycleRegistry; + @VisibleForTesting + LifecycleOwner mLifecycleOwner; + @VisibleForTesting + MutableLiveData<InternetContent> mDataInternetContent = new MutableLiveData<>(); + @AssistedFactory public interface Factory { InternetDialogDelegate create( @@ -205,7 +215,6 @@ public class InternetDialogDelegate implements mInternetDialogManager = internetDialogManager; mInternetDialogController = internetDialogController; mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId(); - mTelephonyManager = mInternetDialogController.getTelephonyManager(); mCanConfigMobileData = canConfigMobileData; mCanConfigWifi = canConfigWifi; mCanChangeWifiState = WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context); @@ -227,6 +236,14 @@ public class InternetDialogDelegate implements mDialog.dismiss(); } mDialog = dialog; + mLifecycleOwner = new LifecycleOwner() { + @NonNull + @Override + public Lifecycle getLifecycle() { + return mLifecycleRegistry; + } + }; + mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner); return dialog; } @@ -249,7 +266,9 @@ public class InternetDialogDelegate implements mWifiNetworkHeight = context.getResources() .getDimensionPixelSize(R.dimen.internet_dialog_wifi_network_height); - + mLifecycleRegistry.setCurrentState(Lifecycle.State.CREATED); + mDataInternetContent.observe( + mLifecycleOwner, (internetContent) -> updateDialogUI(internetContent)); mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title); mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); mDivider = mDialogView.requireViewById(R.id.divider); @@ -294,6 +313,8 @@ public class InternetDialogDelegate implements if (DEBUG) { Log.d(TAG, "onStart"); } + + mLifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED); mInternetDialogController.onStart(this, mCanConfigWifi); if (!mCanConfigWifi) { hideWifiViews(); @@ -315,6 +336,7 @@ public class InternetDialogDelegate implements if (DEBUG) { Log.d(TAG, "onStop"); } + mLifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED); mMobileNetworkLayout.setOnClickListener(null); mConnectedWifListLayout.setOnClickListener(null); if (mSecondaryMobileNetworkLayout != null) { @@ -348,31 +370,50 @@ public class InternetDialogDelegate implements * otherwise {@code false}. */ void updateDialog(boolean shouldUpdateMobileNetwork) { + mBackgroundExecutor.execute(() -> { + mDataInternetContent.postValue(getInternetContent(shouldUpdateMobileNetwork)); + }); + } + + private void updateDialogUI(InternetContent internetContent) { if (DEBUG) { - Log.d(TAG, "updateDialog"); + Log.d(TAG, "updateDialog "); } - mInternetDialogTitle.setText(getDialogTitleText()); - mInternetDialogSubTitle.setText(getSubtitleText()); + + mInternetDialogTitle.setText(internetContent.mInternetDialogTitleString); + mInternetDialogSubTitle.setText(internetContent.mInternetDialogSubTitle); mAirplaneModeButton.setVisibility( - mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE); + internetContent.mIsAirplaneModeEnabled ? View.VISIBLE : View.GONE); - updateEthernet(); - if (shouldUpdateMobileNetwork) { - setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular(), - mInternetDialogController.isCarrierNetworkActive()); - } + updateEthernet(internetContent); + setMobileDataLayout(internetContent); if (!mCanConfigWifi) { return; } - - final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked(); - final boolean isWifiEnabled = mInternetDialogController.isWifiEnabled(); - final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled(); - updateWifiToggle(isWifiEnabled, isDeviceLocked); - updateConnectedWifi(isWifiEnabled, isDeviceLocked); - updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked); - updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked); + updateWifiToggle(internetContent); + updateConnectedWifi(internetContent); + updateWifiListAndSeeAll(internetContent); + updateWifiScanNotify(internetContent); + } + + private InternetContent getInternetContent(boolean shouldUpdateMobileNetwork) { + InternetContent internetContent = new InternetContent(); + internetContent.mShouldUpdateMobileNetwork = shouldUpdateMobileNetwork; + internetContent.mInternetDialogTitleString = getDialogTitleText(); + internetContent.mInternetDialogSubTitle = getSubtitleText(); + internetContent.mActiveNetworkIsCellular = + mInternetDialogController.activeNetworkIsCellular(); + internetContent.mIsCarrierNetworkActive = + mInternetDialogController.isCarrierNetworkActive(); + internetContent.mIsAirplaneModeEnabled = mInternetDialogController.isAirplaneModeEnabled(); + internetContent.mHasEthernet = mInternetDialogController.hasEthernet(); + internetContent.mIsWifiEnabled = mInternetDialogController.isWifiEnabled(); + internetContent.mHasActiveSubIdOnDds = mInternetDialogController.hasActiveSubIdOnDds(); + internetContent.mIsMobileDataEnabled = mInternetDialogController.isMobileDataEnabled(); + internetContent.mIsDeviceLocked = mInternetDialogController.isDeviceLocked(); + internetContent.mIsWifiScanEnabled = mInternetDialogController.isWifiScanEnabled(); + return internetContent; } private void setOnClickListener(SystemUIDialog dialog) { @@ -436,39 +477,39 @@ public class InternetDialogDelegate implements } @MainThread - private void updateEthernet() { + private void updateEthernet(InternetContent internetContent) { mEthernetLayout.setVisibility( - mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE); + internetContent.mHasEthernet ? View.VISIBLE : View.GONE); } - private void setMobileDataLayout(boolean activeNetworkIsCellular, - boolean isCarrierNetworkActive) { - - if (mDialog != null) { - setMobileDataLayout(mDialog, activeNetworkIsCellular, isCarrierNetworkActive); + private void setMobileDataLayout(InternetContent internetContent) { + if (!internetContent.mShouldUpdateMobileNetwork && mDialog == null) { + return; } + setMobileDataLayout(mDialog, internetContent); } - private void setMobileDataLayout(SystemUIDialog dialog, boolean activeNetworkIsCellular, - boolean isCarrierNetworkActive) { - boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive; + private void setMobileDataLayout(SystemUIDialog dialog, InternetContent internetContent) { + boolean isNetworkConnected = + internetContent.mActiveNetworkIsCellular + || internetContent.mIsCarrierNetworkActive; // 1. Mobile network should be gone if airplane mode ON or the list of active // subscriptionId is null. // 2. Carrier network should be gone if airplane mode ON and Wi-Fi is OFF. if (DEBUG) { - Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + isCarrierNetworkActive); + Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + + internetContent.mIsCarrierNetworkActive); } - boolean isWifiEnabled = mInternetDialogController.isWifiEnabled(); - if (!mInternetDialogController.hasActiveSubIdOnDds() - && (!isWifiEnabled || !isCarrierNetworkActive)) { + if (!internetContent.mHasActiveSubIdOnDds && (!internetContent.mIsWifiEnabled + || !internetContent.mIsCarrierNetworkActive)) { mMobileNetworkLayout.setVisibility(View.GONE); if (mSecondaryMobileNetworkLayout != null) { mSecondaryMobileNetworkLayout.setVisibility(View.GONE); } } else { mMobileNetworkLayout.setVisibility(View.VISIBLE); - mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); + mMobileDataToggle.setChecked(internetContent.mIsMobileDataEnabled); mMobileTitleText.setText(getMobileNetworkTitle(mDefaultDataSubId)); String summary = getMobileNetworkSummary(mDefaultDataSubId); if (!TextUtils.isEmpty(summary)) { @@ -508,7 +549,7 @@ public class InternetDialogDelegate implements if (stub != null) { stub.inflate(); } - mSecondaryMobileNetworkLayout = dialog.findViewById( + mSecondaryMobileNetworkLayout = mDialogView.findViewById( R.id.secondary_mobile_network_layout); mSecondaryMobileNetworkLayout.setOnClickListener( this::onClickConnectedSecondarySub); @@ -567,7 +608,7 @@ public class InternetDialogDelegate implements } // Set airplane mode to the summary for carrier network - if (mInternetDialogController.isAirplaneModeEnabled()) { + if (internetContent.mIsAirplaneModeEnabled) { mAirplaneModeSummaryText.setVisibility(View.VISIBLE); mAirplaneModeSummaryText.setText( dialog.getContext().getText(R.string.airplane_mode)); @@ -579,17 +620,18 @@ public class InternetDialogDelegate implements } @MainThread - private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) { - if (mWiFiToggle.isChecked() != isWifiEnabled) { - mWiFiToggle.setChecked(isWifiEnabled); + private void updateWifiToggle(InternetContent internetContent) { + if (mWiFiToggle.isChecked() != internetContent.mIsWifiEnabled) { + mWiFiToggle.setChecked(internetContent.mIsWifiEnabled); } - if (isDeviceLocked) { + if (internetContent.mIsDeviceLocked) { mWifiToggleTitleText.setTextAppearance((mConnectedWifiEntry != null) ? R.style.TextAppearance_InternetDialog_Active : R.style.TextAppearance_InternetDialog); } mTurnWifiOnLayout.setBackground( - (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null); + (internetContent.mIsDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn + : null); if (!mCanChangeWifiState && mWiFiToggle.isEnabled()) { mWiFiToggle.setEnabled(false); @@ -601,8 +643,9 @@ public class InternetDialogDelegate implements } @MainThread - private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) { - if (mDialog == null || !isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) { + private void updateConnectedWifi(InternetContent internetContent) { + if (mDialog == null || !internetContent.mIsWifiEnabled || mConnectedWifiEntry == null + || internetContent.mIsDeviceLocked) { mConnectedWifListLayout.setVisibility(View.GONE); mShareWifiButton.setVisibility(View.GONE); return; @@ -627,8 +670,8 @@ public class InternetDialogDelegate implements } @MainThread - private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) { - if (!isWifiEnabled || isDeviceLocked) { + private void updateWifiListAndSeeAll(InternetContent internetContent) { + if (!internetContent.mIsWifiEnabled || internetContent.mIsDeviceLocked) { mWifiRecyclerView.setVisibility(View.GONE); mSeeAllLayout.setVisibility(View.GONE); return; @@ -670,9 +713,10 @@ public class InternetDialogDelegate implements } @MainThread - private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, - boolean isDeviceLocked) { - if (mDialog == null || isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) { + private void updateWifiScanNotify(InternetContent internetContent) { + if (mDialog == null || internetContent.mIsWifiEnabled + || !internetContent.mIsWifiScanEnabled + || internetContent.mIsDeviceLocked) { mWifiScanNotifyLayout.setVisibility(View.GONE); return; } @@ -805,62 +849,62 @@ public class InternetDialogDelegate implements @Override public void onRefreshCarrierInfo() { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onSimStateChanged() { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override @WorkerThread public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override @WorkerThread public void onLost(Network network) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onSubscriptionsChanged(int defaultDataSubId) { mDefaultDataSubId = defaultDataSubId; - mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId); - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onUserMobileDataStateChanged(boolean enabled) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onServiceStateChanged(ServiceState serviceState) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override @WorkerThread public void onDataConnectionStateChanged(int state, int networkType) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override public void onCarrierNetworkChange(boolean active) { - mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */)); + + updateDialog(true /* shouldUpdateMobileNetwork */); } @Override @@ -912,4 +956,20 @@ public class InternetDialogDelegate implements return mId; } } + + @VisibleForTesting + static class InternetContent { + CharSequence mInternetDialogTitleString = ""; + CharSequence mInternetDialogSubTitle = ""; + boolean mIsAirplaneModeEnabled = false; + boolean mHasEthernet = false; + boolean mShouldUpdateMobileNetwork = false; + boolean mActiveNetworkIsCellular = false; + boolean mIsCarrierNetworkActive = false; + boolean mIsWifiEnabled = false; + boolean mHasActiveSubIdOnDds = false; + boolean mIsMobileDataEnabled = false; + boolean mIsDeviceLocked = false; + boolean mIsWifiScanEnabled = false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt new file mode 100644 index 000000000000..af55f5a9a968 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.ui.viewmodel + +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.Edge +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.qs.ui.adapter.QSSceneAdapter +import com.android.systemui.scene.domain.interactor.SceneBackInteractor +import com.android.systemui.scene.shared.model.SceneFamilies +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map + +/** + * Models the UI state needed to figure out which user actions can trigger navigation from the quick + * settings scene to other scenes. + * + * Different from [QuickSettingsSceneContentViewModel] that models UI state needed for rendering the + * content of the quick settings scene. + */ +class QuickSettingsSceneActionsViewModel +@AssistedInject +constructor( + private val qsSceneAdapter: QSSceneAdapter, + sceneBackInteractor: SceneBackInteractor, +) : SceneActionsViewModel() { + + private val backScene: Flow<SceneKey> = + sceneBackInteractor.backScene + .filter { it != Scenes.QuickSettings } + .map { it ?: Scenes.Shade } + + override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) { + combine( + qsSceneAdapter.isCustomizerShowing, + backScene, + ) { isCustomizing, backScene -> + buildMap<UserAction, UserActionResult> { + if (isCustomizing) { + // TODO(b/332749288) Empty map so there are no back handlers and back can + // close + // customizer + + // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade + // while customizing + } else { + put(Back, UserActionResult(backScene)) + put(Swipe(SwipeDirection.Up), UserActionResult(backScene)) + put( + Swipe(fromSource = Edge.Bottom, direction = SwipeDirection.Up), + UserActionResult(SceneFamilies.Home), + ) + } + } + } + .collectLatest { actions -> setActions(actions) } + } + + @AssistedFactory + interface Factory { + fun create(): QuickSettingsSceneActionsViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt index 7258882e9ffa..55b8f5f0ca98 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt @@ -17,71 +17,34 @@ package com.android.systemui.qs.ui.viewmodel import androidx.lifecycle.LifecycleOwner -import com.android.compose.animation.scene.Back -import com.android.compose.animation.scene.Edge -import com.android.compose.animation.scene.SceneKey -import com.android.compose.animation.scene.Swipe -import com.android.compose.animation.scene.SwipeDirection -import com.android.compose.animation.scene.UserAction -import com.android.compose.animation.scene.UserActionResult -import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.lifecycle.SysUiViewModel import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.QSSceneAdapter -import com.android.systemui.scene.domain.interactor.SceneBackInteractor -import com.android.systemui.scene.shared.model.SceneFamilies -import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import java.util.concurrent.atomic.AtomicBoolean -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map -/** Models UI state and handles user input for the quick settings scene. */ -@SysUISingleton -class QuickSettingsSceneViewModel -@Inject +/** + * Models UI state needed for rendering the content of the quick settings scene. + * + * Different from [QuickSettingsSceneActionsViewModel] that models the UI state needed to figure out + * which user actions can trigger navigation to other scenes. + */ +class QuickSettingsSceneContentViewModel +@AssistedInject constructor( val brightnessMirrorViewModelFactory: BrightnessMirrorViewModel.Factory, val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory, val qsSceneAdapter: QSSceneAdapter, private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, private val footerActionsController: FooterActionsController, - sceneBackInteractor: SceneBackInteractor, val mediaCarouselInteractor: MediaCarouselInteractor, -) { - private val backScene: Flow<SceneKey> = - sceneBackInteractor.backScene - .filter { it != Scenes.QuickSettings } - .map { it ?: Scenes.Shade } - - val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - combine( - qsSceneAdapter.isCustomizerShowing, - backScene, - ) { isCustomizing, backScene -> - buildMap<UserAction, UserActionResult> { - if (isCustomizing) { - // TODO(b/332749288) Empty map so there are no back handlers and back can close - // customizer - - // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade - // while customizing - } else { - put(Back, UserActionResult(backScene)) - put(Swipe(SwipeDirection.Up), UserActionResult(backScene)) - put( - Swipe(fromSource = Edge.Bottom, direction = SwipeDirection.Up), - UserActionResult(SceneFamilies.Home), - ) - } - } - } +) : SysUiViewModel() { val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasAnyMediaOrRecommendation @@ -93,4 +56,9 @@ constructor( } return footerActionsViewModelFactory.create(lifecycleOwner) } + + @AssistedFactory + interface Factory { + fun create(): QuickSettingsSceneContentViewModel + } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt index 103b4a5ff7ef..61a06dbff18f 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scene.kt @@ -20,6 +20,7 @@ import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.lifecycle.Activatable +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow /** @@ -35,7 +36,9 @@ interface Scene : Activatable { /** Uniquely-identifying key for this scene. The key must be unique within its container. */ val key: SceneKey - override suspend fun activate() = Unit + override suspend fun activate(): Nothing { + awaitCancellation() + } /** * The mapping between [UserAction] and destination [UserActionResult]s. diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt index f6924f222e11..8aa601f3ecf0 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt @@ -26,13 +26,12 @@ class SceneWindowRootView( attrs, ) { - private lateinit var viewModel: SceneContainerViewModel - + private var motionEventHandler: SceneContainerViewModel.MotionEventHandler? = null // TODO(b/298525212): remove once Compose exposes window inset bounds. private val windowInsets: MutableStateFlow<WindowInsets?> = MutableStateFlow(null) fun init( - viewModel: SceneContainerViewModel, + viewModelFactory: SceneContainerViewModel.Factory, containerConfig: SceneContainerConfig, sharedNotificationContainer: SharedNotificationContainer, scenes: Set<Scene>, @@ -40,11 +39,13 @@ class SceneWindowRootView( sceneDataSourceDelegator: SceneDataSourceDelegator, alternateBouncerDependencies: AlternateBouncerDependencies, ) { - this.viewModel = viewModel setLayoutInsetsController(layoutInsetController) SceneWindowRootViewBinder.bind( view = this@SceneWindowRootView, - viewModel = viewModel, + viewModelFactory = viewModelFactory, + motionEventHandlerReceiver = { motionEventHandler -> + this.motionEventHandler = motionEventHandler + }, windowInsets = windowInsets, containerConfig = containerConfig, sharedNotificationContainer = sharedNotificationContainer, @@ -69,10 +70,10 @@ class SceneWindowRootView( } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { - viewModel.onMotionEvent(ev) + motionEventHandler?.onMotionEvent(ev) return super.dispatchTouchEvent(ev).also { TouchLogger.logDispatchTouch(TAG, ev, it) - viewModel.onMotionEventComplete() + motionEventHandler?.onMotionEventComplete() } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt index 73a8e4c24578..ad68f17720c5 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt @@ -29,8 +29,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle import com.android.compose.animation.scene.SceneKey import com.android.compose.theme.PlatformTheme import com.android.internal.policy.ScreenDecorationsUtils @@ -39,7 +37,9 @@ import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout import com.android.systemui.common.ui.compose.windowinsets.ScreenDecorProvider import com.android.systemui.keyguard.ui.composable.AlternateBouncer import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies +import com.android.systemui.lifecycle.WindowLifecycleState import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.lifecycle.viewModel import com.android.systemui.res.R import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scene @@ -51,6 +51,7 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map @@ -63,7 +64,8 @@ object SceneWindowRootViewBinder { /** Binds between the view and view-model pertaining to a specific scene container. */ fun bind( view: ViewGroup, - viewModel: SceneContainerViewModel, + viewModelFactory: SceneContainerViewModel.Factory, + motionEventHandlerReceiver: (SceneContainerViewModel.MotionEventHandler?) -> Unit, windowInsets: StateFlow<WindowInsets?>, containerConfig: SceneContainerConfig, sharedNotificationContainer: SharedNotificationContainer, @@ -85,8 +87,11 @@ object SceneWindowRootViewBinder { } view.repeatWhenAttached { - lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { + view.viewModel( + minWindowLifecycleState = WindowLifecycleState.ATTACHED, + factory = { viewModelFactory.create(motionEventHandlerReceiver) }, + ) { viewModel -> + try { view.setViewTreeOnBackPressedDispatcherOwner( object : OnBackPressedDispatcherOwner { override val onBackPressedDispatcher = @@ -140,10 +145,11 @@ object SceneWindowRootViewBinder { onVisibilityChangedInternal(isVisible) } } + awaitCancellation() + } finally { + // Here when destroyed. + view.removeAllViews() } - - // Here when destroyed. - view.removeAllViews() } } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt index c2fd65b6d6cb..b5de1b6209bb 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt @@ -41,7 +41,7 @@ abstract class SceneActionsViewModel : SysUiViewModel() { */ val actions: StateFlow<Map<UserAction, UserActionResult>> = _actions.asStateFlow() - final override suspend fun onActivated() { + final override suspend fun onActivated(): Nothing { try { hydrateActions { state -> _actions.value = state } awaitCancellation() diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt index a28222e9cea0..0b4fb32eaf5b 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt @@ -23,25 +23,26 @@ import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.classifier.Classifier import com.android.systemui.classifier.domain.interactor.FalsingInteractor -import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.lifecycle.SysUiViewModel import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.Scenes -import javax.inject.Inject +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.map /** Models UI state for the scene container. */ -@SysUISingleton class SceneContainerViewModel -@Inject +@AssistedInject constructor( private val sceneInteractor: SceneInteractor, private val falsingInteractor: FalsingInteractor, private val powerInteractor: PowerInteractor, -) { + @Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit, +) : SysUiViewModel() { /** * Keys of all scenes in the container. * @@ -56,6 +57,29 @@ constructor( /** Whether the container is visible. */ val isVisible: StateFlow<Boolean> = sceneInteractor.isVisible + override suspend fun onActivated(): Nothing { + try { + // Sends a MotionEventHandler to the owner of the view-model so they can report + // MotionEvents into the view-model. + motionEventHandlerReceiver( + object : MotionEventHandler { + override fun onMotionEvent(motionEvent: MotionEvent) { + this@SceneContainerViewModel.onMotionEvent(motionEvent) + } + + override fun onMotionEventComplete() { + this@SceneContainerViewModel.onMotionEventComplete() + } + } + ) + awaitCancellation() + } finally { + // Clears the previously-sent MotionEventHandler so the owner of the view-model releases + // their reference to it. + motionEventHandlerReceiver(null) + } + } + /** * Binds the given flow so the system remembers it. * @@ -136,21 +160,22 @@ constructor( } } - private fun replaceSceneFamilies( - destinationScenes: Map<UserAction, UserActionResult>, - ): Flow<Map<UserAction, UserActionResult>> { - return destinationScenes - .mapValues { (_, actionResult) -> - sceneInteractor.resolveSceneFamily(actionResult.toScene).map { scene -> - actionResult.copy(toScene = scene) - } - } - .combineValueFlows() + /** Defines interface for classes that can handle externally-reported [MotionEvent]s. */ + interface MotionEventHandler { + /** Notifies that a [MotionEvent] has occurred. */ + fun onMotionEvent(motionEvent: MotionEvent) + + /** + * Notifies that the previous [MotionEvent] reported by [onMotionEvent] has finished + * processing. + */ + fun onMotionEventComplete() } -} -private fun <K, V> Map<K, Flow<V>>.combineValueFlows(): Flow<Map<K, V>> = - combine( - asIterable().map { (k, fv) -> fv.map { k to it } }, - transform = Array<Pair<K, V>>::toMap, - ) + @AssistedFactory + interface Factory { + fun create( + motionEventHandlerReceiver: (MotionEventHandler?) -> Unit, + ): SceneContainerViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt index 21bbaa5a41f2..606fef0bff62 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt @@ -79,7 +79,7 @@ abstract class ShadeViewProviderModule { @SysUISingleton fun providesWindowRootView( layoutInflater: LayoutInflater, - viewModelProvider: Provider<SceneContainerViewModel>, + viewModelFactory: SceneContainerViewModel.Factory, containerConfigProvider: Provider<SceneContainerConfig>, scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>, layoutInsetController: NotificationInsetsController, @@ -91,7 +91,7 @@ abstract class ShadeViewProviderModule { val sceneWindowRootView = layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView sceneWindowRootView.init( - viewModel = viewModelProvider.get(), + viewModelFactory = viewModelFactory, containerConfig = containerConfigProvider.get(), sharedNotificationContainer = sceneWindowRootView.requireViewById(R.id.shared_notification_container), diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt index 566bc166ed40..00c023540da3 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt @@ -24,6 +24,7 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.domain.interactor.ShadeInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -44,10 +45,11 @@ constructor(private val sceneInteractor: SceneInteractor, shadeInteractor: Shade /** Dictates the alignment of the overlay shade panel on the screen. */ val panelAlignment = shadeInteractor.shadeAlignment - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { sceneInteractor.resolveSceneFamily(SceneFamilies.Home).collectLatest { sceneKey -> _backgroundScene.value = sceneKey } + awaitCancellation() } /** Notifies that the user has clicked the semi-transparent background scrim. */ diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt index 03fdfa9aaa6c..f0e9d41c0fe7 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt @@ -41,6 +41,7 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.Date import java.util.Locale +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -104,7 +105,7 @@ constructor( private val _longerDateText: MutableStateFlow<String> = MutableStateFlow("") val longerDateText: StateFlow<String> = _longerDateText.asStateFlow() - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { coroutineScope { launch { broadcastDispatcher @@ -137,6 +138,8 @@ constructor( launch { shadeInteractor.isQsEnabled.map { !it }.collectLatest { _isDisabled.value = it } } + + awaitCancellation() } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt index a4d34163ba68..fe3bcb5c326c 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt @@ -35,6 +35,7 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -73,10 +74,12 @@ constructor( private val footerActionsControllerInitialized = AtomicBoolean(false) - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered -> _isEmptySpaceClickable.value = !isDeviceEntered } + + awaitCancellation() } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index 14e14f4bd47f..1481b734ff61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -20,7 +20,6 @@ import com.android.systemui.classifier.Classifier import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager -import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager @@ -45,7 +44,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.LSShadeTransitionLogger import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.SplitShadeStateController -import com.android.wm.shell.animation.Interpolators +import com.android.wm.shell.shared.animation.Interpolators import dagger.Lazy import java.io.PrintWriter import javax.inject.Inject diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt index 2b7df7dc937d..67c53d46b4d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt @@ -142,14 +142,15 @@ class NotificationTransitionAnimatorController( } override fun onIntentStarted(willAnimate: Boolean) { + val reason = "onIntentStarted(willAnimate=$willAnimate)" if (ActivityTransitionAnimator.DEBUG_TRANSITION_ANIMATION) { - Log.d(TAG, "onIntentStarted(willAnimate=$willAnimate)") + Log.d(TAG, reason) } notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(willAnimate) notificationEntry.isExpandAnimationRunning = willAnimate if (!willAnimate) { - removeHun(animate = true) + removeHun(animate = true, reason) onFinishAnimationCallback?.run() } } @@ -166,13 +167,18 @@ class NotificationTransitionAnimatorController( } } - private fun removeHun(animate: Boolean) { + private fun removeHun(animate: Boolean, reason: String) { val row = headsUpNotificationRow ?: return // TODO: b/297247841 - Call on the row we're removing, which may differ from notification. HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(notification, animate) - headsUpManager.removeNotification(row.entry.key, true /* releaseImmediately */, animate) + headsUpManager.removeNotification( + row.entry.key, + true /* releaseImmediately */, + animate, + reason + ) } override fun onTransitionAnimationCancelled(newKeyguardOccludedState: Boolean?) { @@ -184,7 +190,7 @@ class NotificationTransitionAnimatorController( // here? notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(false) notificationEntry.isExpandAnimationRunning = false - removeHun(animate = true) + removeHun(animate = true, "onLaunchAnimationCancelled()") onFinishAnimationCallback?.run() } @@ -206,7 +212,7 @@ class NotificationTransitionAnimatorController( notificationEntry.isExpandAnimationRunning = false notificationListContainer.setExpandingNotification(null) applyParams(null) - removeHun(animate = false) + removeHun(animate = false, "onLaunchAnimationEnd()") onFinishAnimationCallback?.run() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index e50d64bcb8f9..ec8566b82aea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -496,7 +496,11 @@ constructor( if (posted?.shouldHeadsUpEver == false) { if (posted.isHeadsUpEntry) { // We don't want this to be interrupting anymore, let's remove it - mHeadsUpManager.removeNotification(posted.key, false /*removeImmediately*/) + mHeadsUpManager.removeNotification( + posted.key, + /* removeImmediately= */ false, + "onEntryUpdated" + ) } else if (posted.isBinding) { // Don't let the bind finish cancelHeadsUpBind(posted.entry) @@ -520,7 +524,11 @@ constructor( val removeImmediatelyForRemoteInput = (mRemoteInputManager.isSpinning(entryKey) && !NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY) - mHeadsUpManager.removeNotification(entry.key, removeImmediatelyForRemoteInput) + mHeadsUpManager.removeNotification( + entry.key, + removeImmediatelyForRemoteInput, + "onEntryRemoved, reason: $reason" + ) } } @@ -721,7 +729,9 @@ constructor( { mHeadsUpManager.removeNotification( entry.key, /* releaseImmediately */ - true + true, + "cancel lifetime extension - extended for reason: " + + "$reason, isSticky: true" ) }, removeAfterMillis @@ -730,7 +740,9 @@ constructor( mExecutor.execute { mHeadsUpManager.removeNotification( entry.key, /* releaseImmediately */ - false + false, + "lifetime extension - extended for reason: $reason" + + ", isSticky: false" ) } mNotifsExtendingLifetime[entry] = null @@ -902,7 +914,7 @@ private class HunMutatorImpl(private val headsUpManager: HeadsUpManager) : HunMu fun commitModifications() { deferred.forEach { (key, releaseImmediately) -> - headsUpManager.removeNotification(key, releaseImmediately) + headsUpManager.removeNotification(key, releaseImmediately, "commitModifications") } deferred.clear() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 41195aa0f72e..fa12bb99eac2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -638,8 +638,11 @@ public class NotificationStackScrollLayoutController implements Dumpable { if (row.isPinned() && !canChildBeDismissed(row) && row.getEntry().getSbn().getNotification().fullScreenIntent == null) { - mHeadsUpManager.removeNotification(row.getEntry().getSbn().getKey(), - true /* removeImmediately */); + mHeadsUpManager.removeNotification( + row.getEntry().getSbn().getKey(), + /* removeImmediately= */ true , + /* reason= */ "onChildSnappedBack" + ); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index bfb624a9287b..a20517981f77 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -59,7 +59,7 @@ constructor( ActivatableFlowDumper by ActivatableFlowDumperImpl(dumpManager, "NotificationScrollViewModel"), SysUiViewModel() { - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { activateFlowDumper() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt index 53fab621173a..2fbb23e30003 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel +import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.lifecycle.SysUiViewModel @@ -25,6 +26,8 @@ import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNoti import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding +import com.android.systemui.util.kotlin.ActivatableFlowDumper +import com.android.systemui.util.kotlin.ActivatableFlowDumperImpl import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.flow.Flow @@ -40,7 +43,13 @@ constructor( shadeInteractor: ShadeInteractor, private val headsUpNotificationInteractor: HeadsUpNotificationInteractor, featureFlags: FeatureFlagsClassic, -) : SysUiViewModel() { + dumpManager: DumpManager, +) : + SysUiViewModel(), + ActivatableFlowDumper by ActivatableFlowDumperImpl( + dumpManager = dumpManager, + tag = "NotificationsPlaceholderViewModel", + ) { /** DEBUG: whether the placeholder should be made slightly visible for positional debugging. */ val isVisualDebuggingEnabled: Boolean = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES) @@ -48,6 +57,10 @@ constructor( /** DEBUG: whether the debug logging should be output. */ val isDebugLoggingEnabled: Boolean = SceneContainerFlag.isEnabled + override suspend fun onActivated(): Nothing { + activateFlowDumper() + } + /** Notifies that the bounds of the notification scrim have changed. */ fun onScrimBoundsChanged(bounds: ShadeScrimBounds?) { interactor.setShadeScrimBounds(bounds) @@ -68,37 +81,35 @@ constructor( headsUpNotificationInteractor.isHeadsUpOrAnimatingAway /** Corner rounding of the stack */ - // TODO(b/359244921): add .dumpWhileCollecting("shadeScrimRounding") - val shadeScrimRounding: Flow<ShadeScrimRounding> = interactor.shadeScrimRounding + val shadeScrimRounding: Flow<ShadeScrimRounding> = + interactor.shadeScrimRounding.dumpWhileCollecting("shadeScrimRounding") /** * The amount [0-1] that the shade or quick settings has been opened. At 0, the shade is closed; * at 1, either the shade or quick settings is open. */ - // TODO(b/359244921): add .dumpValue("expandFraction") - val expandFraction: Flow<Float> = shadeInteractor.anyExpansion + val expandFraction: Flow<Float> = shadeInteractor.anyExpansion.dumpValue("expandFraction") /** * The amount [0-1] that quick settings has been opened. At 0, the shade may be open or closed; * at 1, the quick settings are open. */ - // TODO(b/359244921): add .dumpValue("shadeToQsFraction") - val shadeToQsFraction: Flow<Float> = shadeInteractor.qsExpansion + val shadeToQsFraction: Flow<Float> = shadeInteractor.qsExpansion.dumpValue("shadeToQsFraction") /** * The amount in px that the notification stack should scroll due to internal expansion. This * should only happen when a notification expansion hits the bottom of the screen, so it is * necessary to scroll up to keep expanding the notification. */ - // TODO(b/359244921): add .dumpWhileCollecting("syntheticScroll") - val syntheticScroll: Flow<Float> = interactor.syntheticScroll + val syntheticScroll: Flow<Float> = + interactor.syntheticScroll.dumpWhileCollecting("syntheticScroll") /** * Whether the current touch gesture is overscroll. If true, it means the NSSL has already * consumed part of the gesture. */ - // TODO(b/359244921): add .dumpWhileCollecting("isCurrentGestureOverScroll") - val isCurrentGestureOverscroll: Flow<Boolean> = interactor.isCurrentGestureOverscroll + val isCurrentGestureOverscroll: Flow<Boolean> = + interactor.isCurrentGestureOverscroll.dumpWhileCollecting("isCurrentGestureOverScroll") /** Sets whether the notification stack is scrolled to the top. */ fun setScrolledToTop(scrolledToTop: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index 99f7a75676e1..f63ee7b9520d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -511,7 +511,7 @@ constructor( occludedToAodTransitionViewModel.lockscreenAlpha, occludedToGoneTransitionViewModel.notificationAlpha(viewState), occludedToLockscreenTransitionViewModel.lockscreenAlpha, - primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha, + primaryBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState), glanceableHubToLockscreenTransitionViewModel.keyguardAlpha, lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt index 107bf1edb74f..d4ef42c687e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt @@ -613,8 +613,9 @@ constructor( super.onTransitionAnimationStart(isExpandingFullyAbove) if (Flags.communalHub()) { communalSceneInteractor.snapToScene( - CommunalScenes.Blank, - ActivityTransitionAnimator.TIMINGS.totalDuration + newScene = CommunalScenes.Blank, + loggingReason = "ActivityStarterInternalImpl", + delayMillis = ActivityTransitionAnimator.TIMINGS.totalDuration ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java deleted file mode 100644 index a5388564d5fd..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.statusbar.phone; - -import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE; - -import android.annotation.Nullable; -import android.content.ComponentName; -import android.content.Context; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.hardware.display.ColorDisplayManager; -import android.hardware.display.NightDisplayListener; -import android.os.Handler; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.dagger.NightDisplayListenerModule; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.plugins.qs.QSTile; -import com.android.systemui.qs.AutoAddTracker; -import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.ReduceBrightColorsController; -import com.android.systemui.qs.UserSettingObserver; -import com.android.systemui.qs.external.CustomTile; -import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository; -import com.android.systemui.res.R; -import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastDevice; -import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.DataSaverController.Listener; -import com.android.systemui.statusbar.policy.DeviceControlsController; -import com.android.systemui.statusbar.policy.HotspotController; -import com.android.systemui.statusbar.policy.HotspotController.Callback; -import com.android.systemui.statusbar.policy.SafetyController; -import com.android.systemui.statusbar.policy.WalletController; -import com.android.systemui.util.UserAwareController; -import com.android.systemui.util.settings.SecureSettings; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Objects; - -import javax.inject.Named; - -/** - * Manages which tiles should be automatically added to QS. - */ -public class AutoTileManager implements UserAwareController { - private static final String TAG = "AutoTileManager"; - - public static final String HOTSPOT = "hotspot"; - public static final String SAVER = "saver"; - public static final String INVERSION = "inversion"; - public static final String WORK = "work"; - public static final String NIGHT = "night"; - public static final String CAST = "cast"; - public static final String DEVICE_CONTROLS = "controls"; - public static final String WALLET = "wallet"; - public static final String BRIGHTNESS = "reduce_brightness"; - static final String SETTING_SEPARATOR = ":"; - - private UserHandle mCurrentUser; - private boolean mInitialized; - private final String mSafetySpec; - - protected final Context mContext; - protected final QSHost mHost; - protected final Handler mHandler; - protected final SecureSettings mSecureSettings; - protected final AutoAddTracker mAutoTracker; - private final HotspotController mHotspotController; - private final DataSaverController mDataSaverController; - private final ManagedProfileController mManagedProfileController; - private final NightDisplayListenerModule.Builder mNightDisplayListenerBuilder; - private NightDisplayListener mNightDisplayListener; - private final CastController mCastController; - private final DeviceControlsController mDeviceControlsController; - private final WalletController mWalletController; - private final ReduceBrightColorsController mReduceBrightColorsController; - private final SafetyController mSafetyController; - private final boolean mIsReduceBrightColorsAvailable; - private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>(); - - public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder, - QSHost host, - @Background Handler handler, - SecureSettings secureSettings, - HotspotController hotspotController, - DataSaverController dataSaverController, - ManagedProfileController managedProfileController, - NightDisplayListenerModule.Builder nightDisplayListenerBuilder, - CastController castController, - ReduceBrightColorsController reduceBrightColorsController, - DeviceControlsController deviceControlsController, - WalletController walletController, - SafetyController safetyController, - @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { - mContext = context; - mHost = host; - mSecureSettings = secureSettings; - mCurrentUser = mHost.getUserContext().getUser(); - mAutoTracker = autoAddTrackerBuilder.setUserId(mCurrentUser.getIdentifier()).build(); - mHandler = handler; - mHotspotController = hotspotController; - mDataSaverController = dataSaverController; - mManagedProfileController = managedProfileController; - mNightDisplayListenerBuilder = nightDisplayListenerBuilder; - mCastController = castController; - mReduceBrightColorsController = reduceBrightColorsController; - mIsReduceBrightColorsAvailable = isReduceBrightColorsAvailable; - mDeviceControlsController = deviceControlsController; - mWalletController = walletController; - mSafetyController = safetyController; - String safetySpecClass; - try { - safetySpecClass = - context.getResources().getString(R.string.safety_quick_settings_tile_class); - if (safetySpecClass.length() == 0) { - safetySpecClass = null; - } - } catch (Resources.NotFoundException | NullPointerException e) { - safetySpecClass = null; - } - mSafetySpec = safetySpecClass != null ? CustomTile.toSpec(new ComponentName(mContext - .getPackageManager().getPermissionControllerPackageName(), safetySpecClass)) : null; - } - - /** - * Init method must be called after construction to start listening - */ - public void init() { - QSPipelineFlagsRepository.Utils.assertInLegacyMode(); - if (mInitialized) { - Log.w(TAG, "Trying to re-initialize"); - return; - } - mAutoTracker.initialize(); - populateSettingsList(); - startControllersAndSettingsListeners(); - mInitialized = true; - } - - protected void startControllersAndSettingsListeners() { - if (!mAutoTracker.isAdded(HOTSPOT)) { - mHotspotController.addCallback(mHotspotCallback); - } - if (!mAutoTracker.isAdded(SAVER)) { - mDataSaverController.addCallback(mDataSaverListener); - } - mManagedProfileController.addCallback(mProfileCallback); - - mNightDisplayListener = mNightDisplayListenerBuilder - .setUser(mCurrentUser.getIdentifier()) - .build(); - if (!mAutoTracker.isAdded(NIGHT) - && ColorDisplayManager.isNightDisplayAvailable(mContext)) { - mNightDisplayListener.setCallback(mNightDisplayCallback); - } - if (!mAutoTracker.isAdded(CAST)) { - mCastController.addCallback(mCastCallback); - } - if (!mAutoTracker.isAdded(BRIGHTNESS) && mIsReduceBrightColorsAvailable) { - mReduceBrightColorsController.addCallback(mReduceBrightColorsCallback); - } - // We always want this callback, because if the feature stops being supported, - // we want to remove the tile from AutoAddTracker. That way it will be re-added when the - // feature is reenabled (similar to work tile). - mDeviceControlsController.setCallback(mDeviceControlsCallback); - if (!mAutoTracker.isAdded(WALLET)) { - initWalletController(); - } - if (mSafetySpec != null) { - if (!mAutoTracker.isAdded(mSafetySpec)) { - initSafetyTile(); - } - mSafetyController.addCallback(mSafetyCallback); - } - - int settingsN = mAutoAddSettingList.size(); - for (int i = 0; i < settingsN; i++) { - if (!mAutoTracker.isAdded(mAutoAddSettingList.get(i).mSpec)) { - mAutoAddSettingList.get(i).setListening(true); - } - } - } - - protected void stopListening() { - mHotspotController.removeCallback(mHotspotCallback); - mDataSaverController.removeCallback(mDataSaverListener); - mManagedProfileController.removeCallback(mProfileCallback); - if (ColorDisplayManager.isNightDisplayAvailable(mContext) - && mNightDisplayListener != null) { - mNightDisplayListener.setCallback(null); - } - if (mIsReduceBrightColorsAvailable) { - mReduceBrightColorsController.removeCallback(mReduceBrightColorsCallback); - } - mCastController.removeCallback(mCastCallback); - mDeviceControlsController.removeCallback(); - if (mSafetySpec != null) { - mSafetyController.removeCallback(mSafetyCallback); - } - int settingsN = mAutoAddSettingList.size(); - for (int i = 0; i < settingsN; i++) { - mAutoAddSettingList.get(i).setListening(false); - } - } - - public void destroy() { - stopListening(); - mAutoTracker.destroy(); - } - - /** - * Populates a list with the pairs setting:spec in the config resource. - * <p> - * This will only create {@link AutoAddSetting} objects for those tiles that have not been - * auto-added before, and set the corresponding {@link ContentObserver} to listening. - */ - private void populateSettingsList() { - String [] autoAddList; - try { - autoAddList = mContext.getResources().getStringArray( - R.array.config_quickSettingsAutoAdd); - } catch (Resources.NotFoundException e) { - Log.w(TAG, "Missing config resource"); - return; - } - // getStringArray returns @NotNull, so if we got here, autoAddList is not null - for (String tile : autoAddList) { - String[] split = tile.split(SETTING_SEPARATOR); - if (split.length == 2) { - String setting = split[0]; - String spec = split[1]; - // Populate all the settings. As they may not have been added in other users - AutoAddSetting s = new AutoAddSetting( - mSecureSettings, mHandler, setting, mCurrentUser.getIdentifier(), spec); - mAutoAddSettingList.add(s); - } else { - Log.w(TAG, "Malformed item in array: " + tile); - } - } - } - - /* - * This will be sent off the main thread if needed - */ - @Override - public void changeUser(UserHandle newUser) { - if (!mInitialized) { - throw new IllegalStateException("AutoTileManager not initialized"); - } - if (!Thread.currentThread().equals(mHandler.getLooper().getThread())) { - mHandler.post(() -> changeUser(newUser)); - return; - } - if (newUser.getIdentifier() == mCurrentUser.getIdentifier()) { - return; - } - stopListening(); - mCurrentUser = newUser; - int settingsN = mAutoAddSettingList.size(); - for (int i = 0; i < settingsN; i++) { - mAutoAddSettingList.get(i).setUserId(newUser.getIdentifier()); - } - mAutoTracker.changeUser(newUser); - startControllersAndSettingsListeners(); - } - - @Override - public int getCurrentUserId() { - return mCurrentUser.getIdentifier(); - } - - private final ManagedProfileController.Callback mProfileCallback = - new ManagedProfileController.Callback() { - @Override - public void onManagedProfileChanged() { - if (mManagedProfileController.hasActiveProfile()) { - if (mAutoTracker.isAdded(WORK)) return; - final int position = mAutoTracker.getRestoredTilePosition(WORK); - mHost.addTile(WORK, position); - mAutoTracker.setTileAdded(WORK); - } else { - if (!mAutoTracker.isAdded(WORK)) return; - mHost.removeTile(WORK); - mAutoTracker.setTileRemoved(WORK); - } - } - - @Override - public void onManagedProfileRemoved() { - } - }; - - private final DataSaverController.Listener mDataSaverListener = new Listener() { - @Override - public void onDataSaverChanged(boolean isDataSaving) { - if (mAutoTracker.isAdded(SAVER)) return; - if (isDataSaving) { - mHost.addTile(SAVER); - mAutoTracker.setTileAdded(SAVER); - mHandler.post(() -> mDataSaverController.removeCallback(mDataSaverListener)); - } - } - }; - - private final HotspotController.Callback mHotspotCallback = new Callback() { - @Override - public void onHotspotChanged(boolean enabled, int numDevices) { - if (mAutoTracker.isAdded(HOTSPOT)) return; - if (enabled) { - mHost.addTile(HOTSPOT); - mAutoTracker.setTileAdded(HOTSPOT); - mHandler.post(() -> mHotspotController.removeCallback(mHotspotCallback)); - } - } - }; - - private final DeviceControlsController.Callback mDeviceControlsCallback = - new DeviceControlsController.Callback() { - @Override - public void onControlsUpdate(@Nullable Integer position) { - if (mAutoTracker.isAdded(DEVICE_CONTROLS)) return; - if (position != null && !hasTile(DEVICE_CONTROLS)) { - mHost.addTile(DEVICE_CONTROLS, position); - mAutoTracker.setTileAdded(DEVICE_CONTROLS); - } - mHandler.post(() -> mDeviceControlsController.removeCallback()); - } - - @Override - public void removeControlsAutoTracker() { - mAutoTracker.setTileRemoved(DEVICE_CONTROLS); - } - }; - - private boolean hasTile(String tileSpec) { - if (tileSpec == null) return false; - Collection<QSTile> tiles = mHost.getTiles(); - for (QSTile tile : tiles) { - if (tileSpec.equals(tile.getTileSpec())) { - return true; - } - } - return false; - } - - private void initWalletController() { - if (mAutoTracker.isAdded(WALLET)) return; - Integer position = mWalletController.getWalletPosition(); - - if (position != null) { - mHost.addTile(WALLET, position); - mAutoTracker.setTileAdded(WALLET); - } - } - - private void initSafetyTile() { - if (mSafetySpec == null || mAutoTracker.isAdded(mSafetySpec)) { - return; - } - mHost.addTile(CustomTile.getComponentFromSpec(mSafetySpec), true); - mAutoTracker.setTileAdded(mSafetySpec); - } - - @VisibleForTesting - final NightDisplayListener.Callback mNightDisplayCallback = - new NightDisplayListener.Callback() { - @Override - public void onActivated(boolean activated) { - if (activated) { - addNightTile(); - } - } - - @Override - public void onAutoModeChanged(int autoMode) { - if (autoMode == ColorDisplayManager.AUTO_MODE_CUSTOM_TIME - || autoMode == ColorDisplayManager.AUTO_MODE_TWILIGHT) { - addNightTile(); - } - } - - private void addNightTile() { - if (mAutoTracker.isAdded(NIGHT)) return; - mHost.addTile(NIGHT); - mAutoTracker.setTileAdded(NIGHT); - mHandler.post(() -> mNightDisplayListener.setCallback(null)); - } - }; - - @VisibleForTesting - final ReduceBrightColorsController.Listener mReduceBrightColorsCallback = - new ReduceBrightColorsController.Listener() { - @Override - public void onActivated(boolean activated) { - if (activated) { - addReduceBrightColorsTile(); - } - } - - @Override - public void onFeatureEnabledChanged(boolean enabled) { - if (!enabled) { - mHost.removeTile(BRIGHTNESS); - mHandler.post(() -> mReduceBrightColorsController.removeCallback(this)); - } - } - - private void addReduceBrightColorsTile() { - if (mAutoTracker.isAdded(BRIGHTNESS)) return; - mHost.addTile(BRIGHTNESS); - mAutoTracker.setTileAdded(BRIGHTNESS); - mHandler.post(() -> mReduceBrightColorsController.removeCallback(this)); - } - }; - - @VisibleForTesting - final CastController.Callback mCastCallback = new CastController.Callback() { - @Override - public void onCastDevicesChanged() { - if (mAutoTracker.isAdded(CAST)) return; - - boolean isCasting = false; - for (CastDevice device : mCastController.getCastDevices()) { - if (device.isCasting()) { - isCasting = true; - break; - } - } - - if (isCasting) { - mHost.addTile(CAST); - mAutoTracker.setTileAdded(CAST); - mHandler.post(() -> mCastController.removeCallback(mCastCallback)); - } - } - }; - - @VisibleForTesting - final SafetyController.Listener mSafetyCallback = new SafetyController.Listener() { - @Override - public void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled) { - if (mSafetySpec == null) { - return; - } - - if (isSafetyCenterEnabled && !mAutoTracker.isAdded(mSafetySpec)) { - initSafetyTile(); - } else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) { - mHost.removeTile(mSafetySpec); - mAutoTracker.setTileRemoved(mSafetySpec); - } - } - }; - - @VisibleForTesting - protected UserSettingObserver getSecureSettingForKey(String key) { - for (UserSettingObserver s : mAutoAddSettingList) { - if (Objects.equals(key, s.getKey())) { - return s; - } - } - return null; - } - - /** - * Tracks tiles that should be auto added when a setting changes. - * <p> - * When the setting changes to a value different from 0, if the tile has not been auto added - * before, it will be added and the listener will be stopped. - */ - private class AutoAddSetting extends UserSettingObserver { - private final String mSpec; - - AutoAddSetting( - SecureSettings secureSettings, - Handler handler, - String setting, - int userId, - String tileSpec - ) { - super(secureSettings, handler, setting, userId); - mSpec = tileSpec; - } - - @Override - protected void handleValueChanged(int value, boolean observedChange) { - if (mAutoTracker.isAdded(mSpec)) { - // This should not be listening anymore - mHandler.post(() -> setListening(false)); - return; - } - if (value != 0) { - if (mSpec.startsWith(CustomTile.PREFIX)) { - mHost.addTile(CustomTile.getComponentFromSpec(mSpec), /* end */ true); - } else { - mHost.addTile(mSpec); - } - mAutoTracker.setTileAdded(mSpec); - mHandler.post(() -> setListening(false)); - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index c4fbc37b2dd5..94dd9bbefaa3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -160,6 +160,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.qs.QSFragmentLegacy; import com.android.systemui.qs.QSPanelController; +import com.android.systemui.qs.composefragment.QSFragmentCompose; +import com.android.systemui.qs.flags.QSComposeFragment; import com.android.systemui.res.R; import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor; import com.android.systemui.scene.shared.flag.SceneContainerFlag; @@ -1432,9 +1434,15 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } protected QS createDefaultQSFragment() { + Class<? extends QS> klass; + if (QSComposeFragment.isEnabled()) { + klass = QSFragmentCompose.class; + } else { + klass = QSFragmentLegacy.class; + } return mFragmentService .getFragmentHostManager(getNotificationShadeWindowView()) - .create(QSFragmentLegacy.class); + .create(klass); } private void setUpPresenter() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index ac1015521502..ec92990441ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -193,7 +193,11 @@ public final class DozeServiceHost implements DozeHost { void fireNotificationPulse(NotificationEntry entry) { Runnable pulseSuppressedListener = () -> { mHeadsUpManager.removeNotification( - entry.getKey(), /* releaseImmediately= */ true, /* animate= */ false); + entry.getKey(), + /* releaseImmediately= */ true, + /* animate= */ false, + "fireNotificationPulse" + ); }; Assert.isMainThread(); for (Callback callback : mCallbacks) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 25d9cc76fe3d..544a8a5e5c67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -60,11 +60,6 @@ import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.time.SystemClock; -import kotlinx.coroutines.flow.Flow; -import kotlinx.coroutines.flow.MutableStateFlow; -import kotlinx.coroutines.flow.StateFlow; -import kotlinx.coroutines.flow.StateFlowKt; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; @@ -75,6 +70,11 @@ import java.util.Stack; import javax.inject.Inject; +import kotlinx.coroutines.flow.Flow; +import kotlinx.coroutines.flow.MutableStateFlow; +import kotlinx.coroutines.flow.StateFlow; +import kotlinx.coroutines.flow.StateFlowKt; + /** A implementation of HeadsUpManager for phone. */ @SysUISingleton public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @@ -365,12 +365,14 @@ public class HeadsUpManagerPhone extends BaseHeadsUpManager implements @Override public boolean removeNotification(@NonNull String key, boolean releaseImmediately, - boolean animate) { + boolean animate, @NonNull String reason) { if (animate) { - return removeNotification(key, releaseImmediately); + return removeNotification(key, releaseImmediately, + "removeNotification(animate: true), reason: " + reason); } else { mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false); - boolean removed = removeNotification(key, releaseImmediately); + final boolean removed = removeNotification(key, releaseImmediately, + "removeNotification(animate: false), reason: " + reason); mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true); return removed; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt index 1a4708170a05..460423378dff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt @@ -333,10 +333,6 @@ constructor( } if (intent.isActivity) { assistManagerLazy.get().hideAssist() - // This activity could have started while the device is dreaming, in which case - // the dream would occlude the activity. In order to show the newly started - // activity, we wake from the dream. - keyguardUpdateMonitor.awakenFromDream() } intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index f1787088ab98..e7d5cd19a360 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -16,8 +16,6 @@ package com.android.systemui.statusbar.phone; - - import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; @@ -38,11 +36,8 @@ import com.android.internal.policy.SystemBarUtils; import com.android.systemui.Dependency; import com.android.systemui.Flags; import com.android.systemui.Gefingerpoken; -import com.android.systemui.plugins.DarkIconDispatcher; -import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.res.R; import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer; -import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.window.StatusBarWindowController; import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder; import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel; @@ -55,8 +50,6 @@ public class PhoneStatusBarView extends FrameLayout { private final StatusBarContentInsetsProvider mContentInsetsProvider; private final StatusBarWindowController mStatusBarWindowController; - private DarkReceiver mBattery; - private Clock mClock; private int mRotationOrientation = -1; @Nullable private View mCutoutSpace; @@ -93,8 +86,6 @@ public class PhoneStatusBarView extends FrameLayout { @Override public void onFinishInflate() { super.onFinishInflate(); - mBattery = findViewById(R.id.battery); - mClock = findViewById(R.id.clock); mCutoutSpace = findViewById(R.id.cutout_space_view); updateResources(); @@ -103,9 +94,6 @@ public class PhoneStatusBarView extends FrameLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - // Always have Battery meters in the status bar observe the dark/light modes. - Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery); - Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mClock); if (updateDisplayParameters()) { updateLayoutForCutout(); updateWindowHeight(); @@ -115,8 +103,6 @@ public class PhoneStatusBarView extends FrameLayout { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mBattery); - Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mClock); mDisplayCutout = null; } @@ -136,10 +122,6 @@ public class PhoneStatusBarView extends FrameLayout { updateWindowHeight(); } - void onDensityOrFontScaleChanged() { - mClock.onDensityOrFontScaleChanged(); - } - @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (updateDisplayParameters()) { @@ -316,6 +298,9 @@ public class PhoneStatusBarView extends FrameLayout { } private void updateWindowHeight() { + if (Flags.statusBarStopUpdatingWindowHeight()) { + return; + } mStatusBarWindowController.refreshStatusBarHeight(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index a818c05b1666..468a3c3a49a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -23,10 +23,13 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver +import androidx.annotation.VisibleForTesting import com.android.systemui.Flags import com.android.systemui.Gefingerpoken +import com.android.systemui.battery.BatteryMeterView import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS +import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.res.R import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.ui.view.WindowRootView @@ -35,6 +38,7 @@ import com.android.systemui.shade.ShadeLogger import com.android.systemui.shade.ShadeViewController import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator +import com.android.systemui.statusbar.policy.Clock import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.window.StatusBarWindowStateController import com.android.systemui.unfold.SysUIUnfoldComponent @@ -68,19 +72,27 @@ private constructor( private val viewUtil: ViewUtil, private val configurationController: ConfigurationController, private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory, + private val darkIconDispatcher: DarkIconDispatcher, ) : ViewController<PhoneStatusBarView>(view) { + private lateinit var battery: BatteryMeterView + private lateinit var clock: Clock private lateinit var statusContainer: View private val configurationListener = object : ConfigurationController.ConfigurationListener { override fun onDensityOrFontScaleChanged() { - mView.onDensityOrFontScaleChanged() + clock.onDensityOrFontScaleChanged() } } override fun onViewAttached() { statusContainer = mView.requireViewById(R.id.system_icons) + clock = mView.requireViewById(R.id.clock) + battery = mView.requireViewById(R.id.battery) + + addDarkReceivers() + statusContainer.setOnHoverListener( statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer) ) @@ -133,7 +145,9 @@ private constructor( } } - override fun onViewDetached() { + @VisibleForTesting + public override fun onViewDetached() { + removeDarkReceivers() statusContainer.setOnHoverListener(null) progressProvider?.setReadyToHandleTransition(false) moveFromCenterAnimationController?.onViewDetached() @@ -182,6 +196,16 @@ private constructor( } } + private fun addDarkReceivers() { + darkIconDispatcher.addDarkReceiver(battery) + darkIconDispatcher.addDarkReceiver(clock) + } + + private fun removeDarkReceivers() { + darkIconDispatcher.removeDarkReceiver(battery) + darkIconDispatcher.removeDarkReceiver(clock) + } + inner class PhoneStatusBarViewTouchHandler : Gefingerpoken { override fun onInterceptTouchEvent(event: MotionEvent): Boolean { return if (Flags.statusBarSwipeOverChip()) { @@ -285,6 +309,7 @@ private constructor( private val viewUtil: ViewUtil, private val configurationController: ConfigurationController, private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory, + private val darkIconDispatcher: DarkIconDispatcher, ) { fun create(view: PhoneStatusBarView): PhoneStatusBarViewController { val statusBarMoveFromCenterAnimationController = @@ -309,6 +334,7 @@ private constructor( viewUtil, configurationController, statusOverlayHoverListenerFactory, + darkIconDispatcher, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 5486abba9987..de4d14d31da3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -1007,7 +1007,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mKeyguardMessageAreaController.setIsVisible(isShowingAlternateBouncer); mKeyguardMessageAreaController.setMessage(""); } - mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer); + if (!SceneContainerFlag.isEnabled()) { + mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer); + } if (updateScrim) { mCentralSurfaces.updateScrimController(); @@ -1449,10 +1451,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mNotificationShadeWindowController.setBouncerShowing(primaryBouncerShowing); mCentralSurfaces.setBouncerShowing(primaryBouncerShowing); } - if (primaryBouncerIsOrWillBeShowing != mLastPrimaryBouncerIsOrWillBeShowing || mFirstUpdate - || isPrimaryBouncerShowingChanged) { - mKeyguardUpdateManager.sendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing, - primaryBouncerShowing); + if (!SceneContainerFlag.isEnabled()) { + if (primaryBouncerIsOrWillBeShowing != mLastPrimaryBouncerIsOrWillBeShowing + || mFirstUpdate + || isPrimaryBouncerShowingChanged) { + mKeyguardUpdateManager.sendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing, + primaryBouncerShowing); + } } mFirstUpdate = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index e92058bf034a..0a6e7f59e24e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -230,7 +230,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit Runnable action = () -> { mBubblesManagerOptional.ifPresent(bubblesManager -> bubblesManager.onUserChangedBubble(entry, !entry.isBubble())); - mHeadsUpManager.removeNotification(entry.getKey(), /* releaseImmediately= */ true); + mHeadsUpManager.removeNotification(entry.getKey(), /* releaseImmediately= */ true, + /* reason= */ "onNotificationBubbleIconClicked"); }; if (entry.isBubble()) { // entry is being un-bubbled, no need to unlock @@ -621,7 +622,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // In most cases, when FLAG_AUTO_CANCEL is set, the notification will // become canceled shortly by NoMan, but we can't assume that. - mHeadsUpManager.removeNotification(key, true /* releaseImmediately */); + mHeadsUpManager.removeNotification(key, /* releaseImmediately= */ true, + "removeHunAfterClick"); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TapAgainView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TapAgainView.java index 66ac17eee545..b9cba9903466 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TapAgainView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TapAgainView.java @@ -31,7 +31,7 @@ import androidx.annotation.Nullable; import com.android.settingslib.Utils; import com.android.systemui.res.R; -import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.shared.animation.Interpolators; /** * View to show a toast-like popup on the notification shade and quick settings. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java index 37869587528e..f37393ac6729 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java @@ -40,13 +40,14 @@ import com.android.systemui.res.R; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun; -import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor; import com.android.systemui.statusbar.phone.ExpandHeadsUpOnInlineReply; import com.android.systemui.util.ListenerSet; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.time.SystemClock; +import org.jetbrains.annotations.NotNull; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -191,12 +192,14 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { * enough and needs to be kept around. * @param key the key of the notification to remove * @param releaseImmediately force a remove regardless of earliest removal time + * @param reason reason for removing the notification * @return true if notification is removed, false otherwise */ @Override - public boolean removeNotification(@NonNull String key, boolean releaseImmediately) { + public boolean removeNotification(@NotNull String key, boolean releaseImmediately, + @NonNull String reason) { final boolean isWaiting = mAvalancheController.isWaiting(key); - mLogger.logRemoveNotification(key, releaseImmediately, isWaiting); + mLogger.logRemoveNotification(key, releaseImmediately, isWaiting, reason); if (mAvalancheController.isWaiting(key)) { removeEntry(key, "removeNotification (isWaiting)"); @@ -204,6 +207,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } HeadsUpEntry headsUpEntry = mHeadsUpEntryMap.get(key); if (headsUpEntry == null) { + mLogger.logNullEntry(key, reason); return true; } if (releaseImmediately) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 775f34d54e3f..d281920ab1c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -174,15 +174,24 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC IndentingPrintWriter ipw = asIndenting(pw); ipw.println("BatteryController state:"); ipw.increaseIndent(); - ipw.print("mHasReceivedBattery="); ipw.println(mHasReceivedBattery); - ipw.print("mLevel="); ipw.println(mLevel); - ipw.print("mPluggedIn="); ipw.println(mPluggedIn); - ipw.print("mCharging="); ipw.println(mCharging); - ipw.print("mCharged="); ipw.println(mCharged); - ipw.print("mIsBatteryDefender="); ipw.println(mIsBatteryDefender); - ipw.print("mIsIncompatibleCharging="); ipw.println(mIsIncompatibleCharging); - ipw.print("mPowerSave="); ipw.println(mPowerSave); - ipw.print("mStateUnknown="); ipw.println(mStateUnknown); + ipw.print("mHasReceivedBattery="); + ipw.println(mHasReceivedBattery); + ipw.print("mLevel="); + ipw.println(mLevel); + ipw.print("mPluggedIn="); + ipw.println(mPluggedIn); + ipw.print("mCharging="); + ipw.println(mCharging); + ipw.print("mCharged="); + ipw.println(mCharged); + ipw.print("mIsBatteryDefender="); + ipw.println(mIsBatteryDefender); + ipw.print("mIsIncompatibleCharging="); + ipw.println(mIsIncompatibleCharging); + ipw.print("mPowerSave="); + ipw.println(mPowerSave); + ipw.print("mStateUnknown="); + ipw.println(mStateUnknown); ipw.println("Callbacks:------------------"); // Since the above lines are already indented, we need to indent twice for the callbacks. ipw.increaseIndent(); @@ -272,7 +281,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC } int chargingStatus = intent.getIntExtra(EXTRA_CHARGING_STATUS, CHARGING_POLICY_DEFAULT); - boolean isBatteryDefender = chargingStatus == CHARGING_POLICY_ADAPTIVE_LONGLIFE; + boolean isBatteryDefender = isBatteryDefenderMode(chargingStatus); if (isBatteryDefender != mIsBatteryDefender) { mIsBatteryDefender = isBatteryDefender; fireIsBatteryDefenderChanged(); @@ -359,11 +368,24 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC return mPluggedChargingSource == BatteryManager.BATTERY_PLUGGED_WIRELESS; } - public boolean isBatteryDefender() { + /** + * This method is used for tests only. Returns whether the device is in battery defender + * mode. + */ + @VisibleForTesting + protected boolean isBatteryDefender() { return mIsBatteryDefender; } /** + * Checks whether the device is in battery defender mode based on the current charging + * status. This method can be overridden to have a different definition for its subclasses. + */ + protected boolean isBatteryDefenderMode(int chargingStatus) { + return chargingStatus == CHARGING_POLICY_ADAPTIVE_LONGLIFE; + } + + /** * Returns whether the charging adapter is incompatible. */ public boolean isIncompatibleCharging() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt index 1224275aaf93..e29e069d18e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt @@ -21,13 +21,12 @@ import android.content.Context import android.content.SharedPreferences import android.provider.Settings import android.util.Log -import com.android.systemui.res.R import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.res.R import com.android.systemui.settings.UserContextProvider -import com.android.systemui.statusbar.phone.AutoTileManager import com.android.systemui.statusbar.policy.DeviceControlsController.Callback import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject @@ -35,14 +34,16 @@ import javax.inject.Inject /** * Watches for Device Controls QS Tile activation, which can happen in two ways: * <ol> - * <li>Migration from Power Menu - For existing Android 11 users, create a tile in a high - * priority position. - * <li>Device controls service becomes available - For non-migrated users, create a tile and - * place at the end of active tiles, and initiate seeding where possible. + * <li>Migration from Power Menu - For existing Android 11 users, create a tile in a high priority + * position. + * <li>Device controls service becomes available - For non-migrated users, create a tile and place + * at the end of active tiles, and initiate seeding where possible. * </ol> */ @SysUISingleton -public class DeviceControlsControllerImpl @Inject constructor( +public class DeviceControlsControllerImpl +@Inject +constructor( private val context: Context, private val controlsComponent: ControlsComponent, private val userContextProvider: UserContextProvider, @@ -52,13 +53,14 @@ public class DeviceControlsControllerImpl @Inject constructor( private var callback: Callback? = null internal var position: Int? = null - private val listingCallback = object : ControlsListingController.ControlsListingCallback { - override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) { - if (!serviceInfos.isEmpty()) { - seedFavorites(serviceInfos) + private val listingCallback = + object : ControlsListingController.ControlsListingCallback { + override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) { + if (!serviceInfos.isEmpty()) { + seedFavorites(serviceInfos) + } } } - } companion object { private const val TAG = "DeviceControlsControllerImpl" @@ -80,7 +82,7 @@ public class DeviceControlsControllerImpl @Inject constructor( } /** - * This migration logic assumes that something like [AutoTileManager] is tracking state + * This migration logic assumes that something like [AutoAddTracker] is tracking state * externally, and won't call this method after receiving a response via * [Callback#onControlsUpdate], once per user. Otherwise the calculated position may be * incorrect. @@ -118,16 +120,19 @@ public class DeviceControlsControllerImpl @Inject constructor( } /** - * See if any available control service providers match one of the preferred components. If - * they do, and there are no current favorites for that component, query the preferred - * component for a limited number of suggested controls. + * See if any available control service providers match one of the preferred components. If they + * do, and there are no current favorites for that component, query the preferred component for + * a limited number of suggested controls. */ private fun seedFavorites(serviceInfos: List<ControlsServiceInfo>) { - val preferredControlsPackages = context.getResources().getStringArray( - R.array.config_controlsPreferredPackages) - - val prefs = userContextProvider.userContext.getSharedPreferences( - PREFS_CONTROLS_FILE, Context.MODE_PRIVATE) + val preferredControlsPackages = + context.getResources().getStringArray(R.array.config_controlsPreferredPackages) + + val prefs = + userContextProvider.userContext.getSharedPreferences( + PREFS_CONTROLS_FILE, + Context.MODE_PRIVATE + ) val seededPackages = prefs.getStringSet(PREFS_CONTROLS_SEEDING_COMPLETED, emptySet()) ?: emptySet() @@ -157,21 +162,22 @@ public class DeviceControlsControllerImpl @Inject constructor( if (componentsToSeed.isEmpty()) return controlsController.seedFavoritesForComponents( - componentsToSeed, - { response -> - Log.d(TAG, "Controls seeded: $response") - if (response.accepted) { - addPackageToSeededSet(prefs, response.packageName) - if (position == null) { - position = QS_DEFAULT_POSITION - } - fireControlsUpdate() - - controlsComponent.getControlsListingController().ifPresent { - it.removeCallback(listingCallback) - } + componentsToSeed, + { response -> + Log.d(TAG, "Controls seeded: $response") + if (response.accepted) { + addPackageToSeededSet(prefs, response.packageName) + if (position == null) { + position = QS_DEFAULT_POSITION } - }) + fireControlsUpdate() + + controlsComponent.getControlsListingController().ifPresent { + it.removeCallback(listingCallback) + } + } + } + ) } private fun addPackageToSeededSet(prefs: SharedPreferences, pkg: String) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt index fcf77d5526d4..04fe6b3e9eb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt @@ -96,9 +96,10 @@ interface HeadsUpManager : Dumpable { * * @param key the key of the notification to remove * @param releaseImmediately force a remove regardless of earliest removal time + * @param reason reason for removing the notification * @return true if notification is removed, false otherwise */ - fun removeNotification(key: String, releaseImmediately: Boolean): Boolean + fun removeNotification(key: String, releaseImmediately: Boolean, reason: String): Boolean /** * Try to remove the notification. May not succeed if the notification has not been shown long @@ -107,9 +108,15 @@ interface HeadsUpManager : Dumpable { * @param key the key of the notification to remove * @param releaseImmediately force a remove regardless of earliest removal time * @param animate if true, animate the removal + * @param reason reason for removing the notification * @return true if notification is removed, false otherwise */ - fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean): Boolean + fun removeNotification( + key: String, + releaseImmediately: Boolean, + animate: Boolean, + reason: String + ): Boolean /** Clears all managed notifications. */ fun releaseAllImmediately() @@ -246,11 +253,16 @@ class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager { override fun removeListener(listener: OnHeadsUpChangedListener) {} - override fun removeNotification(key: String, releaseImmediately: Boolean) = false - - override fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean) = + override fun removeNotification(key: String, releaseImmediately: Boolean, reason: String) = false + override fun removeNotification( + key: String, + releaseImmediately: Boolean, + animate: Boolean, + reason: String + ) = false + override fun setAnimationStateHandler(handler: AnimationStateHandler) {} override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt index 80c595fb638b..c6fc54748cbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt @@ -16,244 +16,283 @@ package com.android.systemui.statusbar.policy -import com.android.systemui.log.dagger.NotificationHeadsUpLog import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel.INFO import com.android.systemui.log.core.LogLevel.VERBOSE +import com.android.systemui.log.dagger.NotificationHeadsUpLog import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.logKey import javax.inject.Inject /** Logger for [HeadsUpManager]. */ -class HeadsUpManagerLogger @Inject constructor( - @NotificationHeadsUpLog private val buffer: LogBuffer -) { +class HeadsUpManagerLogger +@Inject +constructor(@NotificationHeadsUpLog private val buffer: LogBuffer) { fun logPackageSnoozed(snoozeKey: String) { - buffer.log(TAG, INFO, { - str1 = snoozeKey - }, { - "package snoozed $str1" - }) + buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package snoozed $str1" }) } fun logPackageUnsnoozed(snoozeKey: String) { - buffer.log(TAG, INFO, { - str1 = snoozeKey - }, { - "package unsnoozed $str1" - }) + buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package unsnoozed $str1" }) } fun logIsSnoozedReturned(snoozeKey: String) { - buffer.log(TAG, INFO, { - str1 = snoozeKey - }, { - "package snoozed when queried $str1" - }) + buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package snoozed when queried $str1" }) } fun logReleaseAllImmediately() { - buffer.log(TAG, INFO, { }, { - "release all immediately" - }) + buffer.log(TAG, INFO, {}, { "release all immediately" }) } fun logShowNotificationRequest(entry: NotificationEntry) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - }, { - "request: show notification $str1" - }) + buffer.log(TAG, INFO, { str1 = entry.logKey }, { "request: show notification $str1" }) } - fun logAvalancheUpdate(caller: String, isEnabled: Boolean, notifEntryKey: String, - outcome: String) { - buffer.log(TAG, INFO, { - str1 = caller - str2 = notifEntryKey - str3 = outcome - bool1 = isEnabled - }, { - "$str1\n\t=> AC[isEnabled:$bool1] update: $str2\n\t=> $str3" - }) + fun logAvalancheUpdate( + caller: String, + isEnabled: Boolean, + notifEntryKey: String, + outcome: String + ) { + buffer.log( + TAG, + INFO, + { + str1 = caller + str2 = notifEntryKey + str3 = outcome + bool1 = isEnabled + }, + { "$str1\n\t=> AC[isEnabled:$bool1] update: $str2\n\t=> $str3" } + ) } - fun logAvalancheDelete(caller: String, isEnabled: Boolean, notifEntryKey: String, - outcome: String) { - buffer.log(TAG, INFO, { - str1 = caller - str2 = notifEntryKey - str3 = outcome - bool1 = isEnabled - }, { - "$str1\n\t=> AC[isEnabled:$bool1] delete: $str2\n\t=> $str3" - }) + fun logAvalancheDelete( + caller: String, + isEnabled: Boolean, + notifEntryKey: String, + outcome: String + ) { + buffer.log( + TAG, + INFO, + { + str1 = caller + str2 = notifEntryKey + str3 = outcome + bool1 = isEnabled + }, + { "$str1\n\t=> AC[isEnabled:$bool1] delete: $str2\n\t=> $str3" } + ) } fun logShowNotification(entry: NotificationEntry) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - }, { - "show notification $str1" - }) + buffer.log(TAG, INFO, { str1 = entry.logKey }, { "show notification $str1" }) } fun logAutoRemoveScheduled(entry: NotificationEntry, delayMillis: Long, reason: String) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - long1 = delayMillis - str2 = reason - }, { - "schedule auto remove of $str1 in $long1 ms reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + long1 = delayMillis + str2 = reason + }, + { "schedule auto remove of $str1 in $long1 ms reason: $str2" } + ) } fun logAutoRemoveRequest(entry: NotificationEntry, reason: String) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - str2 = reason - }, { - "request: reschedule auto remove of $str1 reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + str2 = reason + }, + { "request: reschedule auto remove of $str1 reason: $str2" } + ) } fun logAutoRemoveRescheduled(entry: NotificationEntry, delayMillis: Long, reason: String) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - long1 = delayMillis - str2 = reason - }, { - "reschedule auto remove of $str1 in $long1 ms reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + long1 = delayMillis + str2 = reason + }, + { "reschedule auto remove of $str1 in $long1 ms reason: $str2" } + ) } fun logAutoRemoveCancelRequest(entry: NotificationEntry, reason: String?) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - str2 = reason ?: "unknown" - }, { - "request: cancel auto remove of $str1 reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + str2 = reason ?: "unknown" + }, + { "request: cancel auto remove of $str1 reason: $str2" } + ) } fun logAutoRemoveCanceled(entry: NotificationEntry, reason: String?) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - str2 = reason ?: "unknown" - }, { - "cancel auto remove of $str1 reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + str2 = reason ?: "unknown" + }, + { "cancel auto remove of $str1 reason: $str2" } + ) } fun logRemoveEntryRequest(key: String, reason: String, isWaiting: Boolean) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - str2 = reason - bool1 = isWaiting - }, { - "request: $str2 => remove entry $str1 isWaiting: $isWaiting" - }) + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + str2 = reason + bool1 = isWaiting + }, + { "request: $str2 => remove entry $str1 isWaiting: $isWaiting" } + ) } fun logRemoveEntry(key: String, reason: String, isWaiting: Boolean) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - str2 = reason - bool1 = isWaiting - }, { - "$str2 => remove entry $str1 isWaiting: $isWaiting" - }) + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + str2 = reason + bool1 = isWaiting + }, + { "$str2 => remove entry $str1 isWaiting: $isWaiting" } + ) } fun logUnpinEntryRequest(key: String) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - }, { - "request: unpin entry $str1" - }) + buffer.log(TAG, INFO, { str1 = logKey(key) }, { "request: unpin entry $str1" }) } fun logUnpinEntry(key: String) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - }, { - "unpin entry $str1" - }) + buffer.log(TAG, INFO, { str1 = logKey(key) }, { "unpin entry $str1" }) + } + + fun logRemoveNotification( + key: String, + releaseImmediately: Boolean, + isWaiting: Boolean, + reason: String + ) { + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + bool1 = releaseImmediately + bool2 = isWaiting + str2 = reason + }, + { + "remove notification $str1 releaseImmediately: $bool1 isWaiting: $bool2 " + + "reason: $str2" + } + ) } - fun logRemoveNotification(key: String, releaseImmediately: Boolean, isWaiting: Boolean) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - bool1 = releaseImmediately - bool2 = isWaiting - }, { - "remove notification $str1 releaseImmediately: $bool1 isWaiting: $bool2" - }) + fun logNullEntry(key: String, reason: String) { + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + str2 = reason + }, + { "remove notification $str1 when headsUpEntry is null, reason: $str2" } + ) } fun logNotificationActuallyRemoved(entry: NotificationEntry) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - }, { - "notification removed $str1 " - }) + buffer.log(TAG, INFO, { str1 = entry.logKey }, { "notification removed $str1 " }) } fun logUpdateNotificationRequest(key: String, alert: Boolean, hasEntry: Boolean) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - bool1 = alert - bool2 = hasEntry - }, { - "request: update notification $str1 alert: $bool1 hasEntry: $bool2" - }) + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + bool1 = alert + bool2 = hasEntry + }, + { "request: update notification $str1 alert: $bool1 hasEntry: $bool2" } + ) } fun logUpdateNotification(key: String, alert: Boolean, hasEntry: Boolean) { - buffer.log(TAG, INFO, { - str1 = logKey(key) - bool1 = alert - bool2 = hasEntry - }, { - "update notification $str1 alert: $bool1 hasEntry: $bool2" - }) + buffer.log( + TAG, + INFO, + { + str1 = logKey(key) + bool1 = alert + bool2 = hasEntry + }, + { "update notification $str1 alert: $bool1 hasEntry: $bool2" } + ) } fun logUpdateEntry(entry: NotificationEntry, updatePostTime: Boolean, reason: String?) { - buffer.log(TAG, INFO, { - str1 = entry.logKey - bool1 = updatePostTime - str2 = reason ?: "unknown" - }, { - "update entry $str1 updatePostTime: $bool1 reason: $str2" - }) + buffer.log( + TAG, + INFO, + { + str1 = entry.logKey + bool1 = updatePostTime + str2 = reason ?: "unknown" + }, + { "update entry $str1 updatePostTime: $bool1 reason: $str2" } + ) } fun logSnoozeLengthChange(packageSnoozeLengthMs: Int) { - buffer.log(TAG, INFO, { - int1 = packageSnoozeLengthMs - }, { - "snooze length changed: ${int1}ms" - }) + buffer.log( + TAG, + INFO, + { int1 = packageSnoozeLengthMs }, + { "snooze length changed: ${int1}ms" } + ) } fun logSetEntryPinned(entry: NotificationEntry, isPinned: Boolean, reason: String) { - buffer.log(TAG, VERBOSE, { - str1 = entry.logKey - bool1 = isPinned - str2 = reason - }, { - "$str2 => set entry pinned $str1 pinned: $bool1" - }) + buffer.log( + TAG, + VERBOSE, + { + str1 = entry.logKey + bool1 = isPinned + str2 = reason + }, + { "$str2 => set entry pinned $str1 pinned: $bool1" } + ) } fun logUpdatePinnedMode(hasPinnedNotification: Boolean) { - buffer.log(TAG, INFO, { - bool1 = hasPinnedNotification - }, { - "has pinned notification changed to $bool1" - }) + buffer.log( + TAG, + INFO, + { bool1 = hasPinnedNotification }, + { "has pinned notification changed to $bool1" } + ) } } -private const val TAG = "HeadsUpManager"
\ No newline at end of file +private const val TAG = "HeadsUpManager" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt index 8aa989ff390f..4f7749b9bd57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt @@ -57,6 +57,7 @@ constructor( private val activityStarter: ActivityStarter, // Using a provider to avoid a circular dependency. private val viewModel: Provider<ModesDialogViewModel>, + private val dialogEventLogger: ModesDialogEventLogger, @Main private val mainCoroutineContext: CoroutineContext, ) : SystemUIDialog.Delegate { // NOTE: This should only be accessed/written from the main thread. @@ -102,7 +103,9 @@ constructor( ) } - private fun openSettings(dialog: SystemUIDialog) { + @VisibleForTesting + fun openSettings(dialog: SystemUIDialog) { + dialogEventLogger.logDialogSettings() val animationController = dialogTransitionAnimator.createActivityTransitionController(dialog) if (animationController == null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt new file mode 100644 index 000000000000..33ed419afef2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy.ui.dialog + +import com.android.internal.logging.UiEventLogger +import com.android.settingslib.notification.modes.ZenMode +import com.android.systemui.qs.QSModesEvent +import javax.inject.Inject + +class ModesDialogEventLogger +@Inject +constructor( + private val uiEventLogger: UiEventLogger, +) { + + fun logModeOn(mode: ZenMode) { + val id = + if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_ON else QSModesEvent.QS_MODES_MODE_ON + uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName) + } + + fun logModeOff(mode: ZenMode) { + val id = + if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_OFF else QSModesEvent.QS_MODES_MODE_OFF + uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName) + } + + fun logModeSettings(mode: ZenMode) { + val id = + if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_SETTINGS + else QSModesEvent.QS_MODES_MODE_SETTINGS + uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName) + } + + fun logOpenDurationDialog(mode: ZenMode) { + // should only occur for manual Do Not Disturb. + if (!mode.isManualDnd) { + return + } + uiEventLogger.log(QSModesEvent.QS_MODES_DURATION_DIALOG) + } + + fun logDialogSettings() { + uiEventLogger.log(QSModesEvent.QS_MODES_SETTINGS) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt index 44b692fcb786..5772099706b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt @@ -30,6 +30,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate +import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogEventLogger import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow @@ -49,6 +50,7 @@ constructor( zenModeInteractor: ZenModeInteractor, @Background val bgDispatcher: CoroutineDispatcher, private val dialogDelegate: ModesDialogDelegate, + private val dialogEventLogger: ModesDialogEventLogger, ) { private val zenDialogMetricsLogger = QSZenModeDialogMetricsLogger(context) @@ -94,14 +96,17 @@ constructor( if (!mode.rule.isEnabled) { openSettings(mode) } else if (mode.isActive) { + dialogEventLogger.logModeOff(mode) zenModeInteractor.deactivateMode(mode) } else { if (mode.rule.isManualInvocationAllowed) { if (zenModeInteractor.shouldAskForZenDuration(mode)) { + dialogEventLogger.logOpenDurationDialog(mode) // NOTE: The dialog handles turning on the mode itself. val dialog = makeZenModeDialog() dialog.show() } else { + dialogEventLogger.logModeOn(mode) zenModeInteractor.activateMode(mode) } } @@ -114,6 +119,7 @@ constructor( .flowOn(bgDispatcher) private fun openSettings(mode: ZenMode) { + dialogEventLogger.logModeSettings(mode) val intent: Intent = Intent(ACTION_AUTOMATIC_ZEN_RULE_SETTINGS) .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, mode.id) diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt index ade6c3df2e0f..ef9f8ff9de0d 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt @@ -170,7 +170,7 @@ abstract class FlowDumperImpl( * [Activatable.activate()][com.android.systemui.lifecycle.Activatable.activate]. */ interface ActivatableFlowDumper : FlowDumper { - suspend fun activateFlowDumper() + suspend fun activateFlowDumper(): Nothing } /** @@ -190,7 +190,7 @@ class ActivatableFlowDumperImpl( private val registration = object : SafeActivatable() { - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { try { dumpManager.registerCriticalDumpable( dumpManagerName, @@ -205,7 +205,7 @@ class ActivatableFlowDumperImpl( private val dumpManagerName = "[$idString] $tag" - override suspend fun activateFlowDumper() { + override suspend fun activateFlowDumper(): Nothing { registration.activate() } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 066bfc5c588d..1522cc490b43 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -165,6 +165,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa private boolean mShowSafetyWarning; private long mLastToggledRingerOn; private boolean mDeviceInteractive = true; + boolean mInAudioSharing = false; private VolumePolicy mVolumePolicy; @GuardedBy("this") @@ -295,6 +296,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa mJavaAdapter.alwaysCollectFlow( mAudioSharingInteractor.getVolume(), this::handleAudioSharingStreamVolumeChanges); + mJavaAdapter.alwaysCollectFlow( + mAudioSharingInteractor.isInAudioSharing(), + inSharing -> mInAudioSharing = inSharing); } } @@ -510,11 +514,18 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa // Since their values overlap with DEVICE_OUT_EARPIECE and DEVICE_OUT_SPEAKER. // Anyway, we can check BLE devices by using just DEVICE_OUT_BLE_HEADSET. final boolean routedToBluetooth = - (mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) & - (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP | - AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | - AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | - AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0; + // TODO(b/359737651): Need audio support to return broadcast mask. + // For now, mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) will return + // AudioManager.DEVICE_NONE, so we also need to check if the device is in audio + // sharing here. + mInAudioSharing + || (mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) + & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP + | AudioManager + .DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES + | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER + | AudioManager.DEVICE_OUT_BLE_HEADSET)) + != 0; changed |= updateStreamRoutedToBluetoothW(stream, routedToBluetooth); } else if (stream == AudioManager.STREAM_VOICE_CALL) { final boolean routedToBluetooth = @@ -813,6 +824,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa ss.dynamic = true; ss.levelMin = mAudioSharingInteractor.getVolumeMin(); ss.levelMax = mAudioSharingInteractor.getVolumeMax(); + ss.routedToBluetooth = true; if (ss.level != volume) { ss.level = volume; } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index e56f6b32c085..2468449fb859 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -1892,8 +1892,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, .equals(ss.remoteLabel)) { addRow( stream, - R.drawable.ic_volume_media, - R.drawable.ic_volume_media_mute, + R.drawable.ic_volume_media_bt, + R.drawable.ic_volume_media_bt_mute, true, false, true); diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt index 154737c71b9e..4f77cd04f5fa 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt @@ -26,7 +26,6 @@ import com.android.settingslib.media.MediaDevice import com.android.settingslib.media.MediaDevice.MediaDeviceType import com.android.settingslib.media.PhoneMediaDevice import com.android.settingslib.volume.data.repository.AudioRepository -import com.android.settingslib.volume.data.repository.AudioSharingRepository import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -37,7 +36,6 @@ import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flatMapLatest @@ -60,7 +58,6 @@ constructor( private val bluetoothAdapter: BluetoothAdapter?, private val deviceIconInteractor: DeviceIconInteractor, private val mediaOutputInteractor: MediaOutputInteractor, - audioSharingRepository: AudioSharingRepository, ) { val currentAudioDevice: StateFlow<AudioOutputDevice> = @@ -80,9 +77,6 @@ constructor( .flowOn(backgroundCoroutineContext) .stateIn(scope, SharingStarted.Eagerly, AudioOutputDevice.Unknown) - /** Whether the device is in audio sharing */ - val isInAudioSharing: Flow<Boolean> = audioSharingRepository.inAudioSharing - private fun AudioDeviceInfo.toAudioOutputDevice(): AudioOutputDevice { if ( BluetoothAdapter.checkBluetoothAddress(address) && diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt index 2170c36ec019..9aed8ab8f2e2 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioSharingInteractor.kt @@ -36,11 +36,15 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext interface AudioSharingInteractor { + /** Audio sharing state on the device. */ + val isInAudioSharing: Flow<Boolean> + /** Audio sharing secondary headset volume changes. */ val volume: Flow<Int?> @@ -76,6 +80,7 @@ constructor( private val audioVolumeInteractor: AudioVolumeInteractor, private val audioSharingRepository: AudioSharingRepository ) : AudioSharingInteractor { + override val isInAudioSharing: Flow<Boolean> = audioSharingRepository.inAudioSharing override val volume: Flow<Int?> = combine(audioSharingRepository.secondaryGroupId, audioSharingRepository.volumeMap) { @@ -125,13 +130,13 @@ constructor( } private companion object { - const val TAG = "AudioSharingInteractor" const val DEFAULT_VOLUME = 20 } } @SysUISingleton class AudioSharingInteractorEmptyImpl @Inject constructor() : AudioSharingInteractor { + override val isInAudioSharing: Flow<Boolean> = flowOf(false) override val volume: Flow<Int?> = emptyFlow() override val volumeMin: Int = EMPTY_VOLUME override val volumeMax: Int = EMPTY_VOLUME diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt index ed25129ff082..a270d5ffa9de 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.volume.panel.component.mediaoutput.domain.interacto import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.systemui.volume.domain.interactor.AudioOutputInteractor +import com.android.systemui.volume.domain.interactor.AudioSharingInteractor import com.android.systemui.volume.domain.model.AudioOutputDevice import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaOutputComponentModel import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState @@ -49,11 +50,12 @@ constructor( private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, audioOutputInteractor: AudioOutputInteractor, audioModeInteractor: AudioModeInteractor, - interactor: MediaOutputInteractor, + mediaOutputInteractor: MediaOutputInteractor, + audioSharingInteractor: AudioSharingInteractor, ) { private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> = - interactor.defaultActiveMediaSession + mediaOutputInteractor.defaultActiveMediaSession .filterData() .flatMapLatest { session -> if (session == null) { @@ -77,7 +79,7 @@ constructor( val mediaOutputModel: StateFlow<Result<MediaOutputComponentModel>> = audioModeInteractor.isOngoingCall .flatMapLatest { isOngoingCall -> - audioOutputInteractor.isInAudioSharing.flatMapLatest { isInAudioSharing -> + audioSharingInteractor.isInAudioSharing.flatMapLatest { isInAudioSharing -> if (isOngoingCall) { currentAudioDevice.map { MediaOutputComponentModel.Calling(it, isInAudioSharing) diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt index fa400593c990..0451ce6d9fce 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt @@ -19,6 +19,7 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import android.media.AudioDeviceInfo import android.media.AudioManager import com.android.settingslib.volume.data.repository.AudioRepository +import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession @@ -42,6 +43,7 @@ constructor( @VolumePanelScope scope: CoroutineScope, mediaOutputInteractor: MediaOutputInteractor, audioRepository: AudioRepository, + audioModeInteractor: AudioModeInteractor, ) { val volumePanelSliders: StateFlow<List<SliderType>> = @@ -49,9 +51,14 @@ constructor( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession.filterData(), audioRepository.communicationDevice, - ) { activeSessions, defaultSession, communicationDevice -> + audioModeInteractor.isOngoingCall, + ) { activeSessions, defaultSession, communicationDevice, isOngoingCall -> coroutineScope { val viewModels = buildList { + if (isOngoingCall) { + addCall(communicationDevice?.type) + } + if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addSession(activeSessions.remote) addStream(AudioManager.STREAM_MUSIC) @@ -60,11 +67,10 @@ constructor( addSession(activeSessions.remote) } - if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { - addStream(AudioManager.STREAM_BLUETOOTH_SCO) - } else { - addStream(AudioManager.STREAM_VOICE_CALL) + if (!isOngoingCall) { + addCall(communicationDevice?.type) } + addStream(AudioManager.STREAM_RING) addStream(AudioManager.STREAM_NOTIFICATION) addStream(AudioManager.STREAM_ALARM) @@ -74,6 +80,14 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) + private fun MutableList<SliderType>.addCall(communicationDeviceType: Int?) { + if (communicationDeviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { + addStream(AudioManager.STREAM_BLUETOOTH_SCO) + } else { + addStream(AudioManager.STREAM_VOICE_CALL) + } + } + private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { add(SliderType.MediaDeviceCast(remoteMediaDeviceSession)) diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt index 4b4d69a31db4..45732deb9aa6 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel +import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor @@ -35,9 +36,11 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn @@ -58,24 +61,31 @@ constructor( mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, + audioModeInteractor: AudioModeInteractor, streamsInteractor: AudioSlidersInteractor, ) { private val mutableIsExpanded = MutableStateFlow<Boolean?>(null) - private val isPlaybackActive: Flow<Boolean?> = - mediaOutputInteractor.defaultActiveMediaSession - .filterData() - .flatMapLatest { session -> - if (session == null) { - flowOf(false) - } else { - mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true } - } + private val isActive: Flow<Boolean?> = + combine( + audioModeInteractor.isOngoingCall, + mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session + -> + if (session == null) { + flowOf(false) + } else { + mediaDeviceSessionInteractor.playbackState(session).map { + it?.isActive == true + } + } + }, + ) { isOngoingCall, isPlaybackActive -> + isOngoingCall || isPlaybackActive } - .onEach { isPlaybackActive -> mutableIsExpanded.value = !isPlaybackActive } .stateIn(scope, SharingStarted.Eagerly, null) + private val portraitExpandable: Flow<SlidersExpandableViewModel> = - isPlaybackActive + isActive .filterNotNull() .flatMapLatest { isActive -> if (isActive) { @@ -105,6 +115,10 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) + init { + isActive.filterNotNull().onEach { mutableIsExpanded.value = !it }.launchIn(scope) + } + fun isExpandable(isPortrait: Boolean): Flow<SlidersExpandableViewModel> { return if (isPortrait) { portraitExpandable diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java index 2e29bbd33f92..b1c6455a6e57 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java @@ -21,6 +21,7 @@ import static android.app.WallpaperManager.FLAG_SYSTEM; import static android.app.WallpaperManager.SetWallpaperFlags; import static com.android.systemui.Flags.fixImageWallpaperCrashSurfaceAlreadyReleased; +import static com.android.window.flags.Flags.multiCrop; import static com.android.window.flags.Flags.offloadColorExtraction; import android.annotation.Nullable; @@ -190,7 +191,10 @@ public class ImageWallpaper extends WallpaperService { } mWallpaperManager = getDisplayContext().getSystemService(WallpaperManager.class); mSurfaceHolder = surfaceHolder; - Rect dimensions = mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true); + Rect dimensions = !multiCrop() + ? mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true) + : mWallpaperManager.peekBitmapDimensionsAsUser(getSourceFlag(), true, + mUserTracker.getUserId()); int width = Math.max(MIN_SURFACE_WIDTH, dimensions.width()); int height = Math.max(MIN_SURFACE_HEIGHT, dimensions.height()); mSurfaceHolder.setFixedSize(width, height); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 075d8ae0adac..7aa415b64316 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -102,6 +102,7 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.flag.junit.FlagsParameterization; import android.service.dreams.IDreamManager; import android.service.trust.TrustAgentService; import android.telephony.ServiceState; @@ -111,9 +112,9 @@ import android.telephony.TelephonyManager; import android.testing.TestableLooper; import android.text.TextUtils; -import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.compose.animation.scene.ObservableTransitionState; import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.internal.foldables.FoldGracePeriodProvider; import com.android.internal.jank.InteractionJankMonitor; @@ -129,6 +130,7 @@ import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider; +import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig; import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfigImpl; @@ -138,9 +140,13 @@ import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStat import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus; import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.SceneContainerFlagParameterizationKt; import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; +import com.android.systemui.scene.shared.model.Scenes; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; @@ -149,6 +155,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.domain.interactor.SelectedUserInteractor; +import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.settings.GlobalSettings; import org.junit.After; @@ -175,8 +182,11 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(ParameterizedAndroidJunit4.class) @TestableLooper.RunWithLooper public class KeyguardUpdateMonitorTest extends SysuiTestCase { private static final String PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY = @@ -277,6 +287,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private SelectedUserInteractor mSelectedUserInteractor; @Mock private DeviceEntryFaceAuthInteractor mFaceAuthInteractor; + @Mock + private AlternateBouncerInteractor mAlternateBouncerInteractor; + @Mock + private JavaAdapter mJavaAdapter; + @Mock + private SceneInteractor mSceneInteractor; @Captor private ArgumentCaptor<FaceAuthenticationListener> mFaceAuthenticationListener; @@ -301,6 +317,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mFingerprintAuthenticatorsRegisteredCallback; private final InstanceId mKeyguardInstanceId = InstanceId.fakeInstanceId(999); + @Parameters(name = "{0}") + public static List<FlagsParameterization> getParams() { + return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag(); + } + + public KeyguardUpdateMonitorTest(FlagsParameterization flags) { + super(); + mSetFlagsRule.setFlagsParameterization(flags); + } + @Before public void setup() throws RemoteException { mKosmos = new KosmosJavaAdapter(this); @@ -993,7 +1019,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verifyFingerprintAuthenticateNeverCalled(); // WHEN alternate bouncer is shown mKeyguardUpdateMonitor.setKeyguardShowing(true, true); - mKeyguardUpdateMonitor.setAlternateBouncerShowing(true); + mKeyguardUpdateMonitor.setAlternateBouncerVisibility(true); // THEN make sure FP listening begins verifyFingerprintAuthenticateCall(); @@ -1489,7 +1515,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testShouldNotListenForUdfps_whenInLockDown() { // GIVEN a "we should listen for udfps" state - setKeyguardBouncerVisibility(false /* isVisible */); + mKeyguardUpdateMonitor.setPrimaryBouncerVisibility(false /* isVisible */); mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true); @@ -2124,7 +2150,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verifyFingerprintAuthenticateNeverCalled(); mKeyguardUpdateMonitor.setKeyguardShowing(true, true); - mKeyguardUpdateMonitor.setAlternateBouncerShowing(true); + mKeyguardUpdateMonitor.setAlternateBouncerVisibility(true); verifyFingerprintAuthenticateCall(); } @@ -2323,12 +2349,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } private void bouncerFullyVisible() { - setKeyguardBouncerVisibility(true); - } - - private void setKeyguardBouncerVisibility(boolean isVisible) { - mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(isVisible, isVisible); - mTestableLooper.processAllMessages(); + mKeyguardUpdateMonitor.setPrimaryBouncerVisibility(true); } private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) { @@ -2434,7 +2455,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mPackageManager, mFingerprintManager, mBiometricManager, mFaceWakeUpTriggersConfig, mDevicePostureController, Optional.of(mInteractiveToAuthProvider), - mTaskStackChangeListeners, mSelectedUserInteractor, mActivityTaskManager); + mTaskStackChangeListeners, mSelectedUserInteractor, mActivityTaskManager, + () -> mAlternateBouncerInteractor, + () -> mJavaAdapter, + () -> mSceneInteractor); + setAlternateBouncerVisibility(false); + setPrimaryBouncerVisibility(false); setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker); start(); } @@ -2458,5 +2484,25 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { protected int getBiometricLockoutDelay() { return 0; } + + private void setPrimaryBouncerVisibility(boolean isVisible) { + if (SceneContainerFlag.isEnabled()) { + ObservableTransitionState transitionState = new ObservableTransitionState.Idle( + isVisible ? Scenes.Bouncer : Scenes.Lockscreen); + when(mSceneInteractor.getTransitionState()).thenReturn( + MutableStateFlow(transitionState)); + onTransitionStateChanged(transitionState); + } else { + sendPrimaryBouncerChanged(isVisible, isVisible); + mTestableLooper.processAllMessages(); + } + } + + private void setAlternateBouncerVisibility(boolean isVisible) { + if (SceneContainerFlag.isEnabled()) { + when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(isVisible); + } + onAlternateBouncerVisibilityChange(isVisible); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java index ff47fd1106bb..c74d340ee325 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java @@ -32,10 +32,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.display.DisplayManager; import android.os.RemoteException; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.testing.TestableLooper; import android.view.Display; @@ -49,7 +45,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; -import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.model.SysUiState; import com.android.systemui.recents.OverviewProxyService; @@ -58,7 +53,6 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.util.settings.SecureSettings; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -73,9 +67,6 @@ import org.mockito.MockitoAnnotations; @TestableLooper.RunWithLooper(setAsMainLooper = true) public class IMagnificationConnectionTest extends SysuiTestCase { - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; @Mock private AccessibilityManager mAccessibilityManager; @@ -198,22 +189,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { } @Test - @RequiresFlagsDisabled(Flags.FLAG_DELAY_SHOW_MAGNIFICATION_BUTTON) - public void showMagnificationButton_flagOff_directlyShowButton() throws RemoteException { - // magnification settings panel should not be showing - assertFalse(mMagnification.isMagnificationSettingsPanelShowing(TEST_DISPLAY)); - - mIMagnificationConnection.showMagnificationButton(TEST_DISPLAY, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); - processAllPendingMessages(); - - verify(mModeSwitchesController).showButton(TEST_DISPLAY, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); - } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_DELAY_SHOW_MAGNIFICATION_BUTTON) - public void showMagnificationButton_flagOn_delayedShowButton() throws RemoteException { + public void showMagnificationButton_delayedShowButton() throws RemoteException { // magnification settings panel should not be showing assertFalse(mMagnification.isMagnificationSettingsPanelShowing(TEST_DISPLAY)); @@ -243,12 +219,9 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // showMagnificationButton request to Magnification. processAllPendingMessages(); - // If the flag is on, the isMagnificationSettingsShowing will be checked after timeout, so + // The isMagnificationSettingsShowing will be checked after timeout, so // process all message after a timeout here to verify the showButton will not be called. - int timeout = Flags.delayShowMagnificationButton() - ? DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100 - : 0; - processAllPendingMessages(timeout); + processAllPendingMessages(DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100); verify(mModeSwitchesController, never()).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } @@ -262,7 +235,6 @@ public class IMagnificationConnectionTest extends SysuiTestCase { } @Test - @RequiresFlagsEnabled(Flags.FLAG_DELAY_SHOW_MAGNIFICATION_BUTTON) public void removeMagnificationButton_delayingShowButton_doNotShowButtonAfterTimeout() throws RemoteException { // magnification settings panel should not be showing diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java index 9507077a89ae..7c0c5c209363 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java @@ -22,6 +22,9 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.WindowInsets.Type.systemBars; +import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MAX_VALUE; +import static com.android.internal.accessibility.common.MagnificationConstants.SCALE_MIN_VALUE; + import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; @@ -429,7 +432,7 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { mSettingView = mWindowMagnificationSettings.getSettingView(); mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_slider); assertThat(mZoomSeekbar.getProgress()).isEqualTo(10); - assertThat(mZoomSeekbar.getMax()).isEqualTo(70); + assertThat(mZoomSeekbar.getMax()).isEqualTo(getSeekBarMax()); } @Test @@ -473,29 +476,26 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { @Test public void seekbarProgress_maxMagnificationBefore_seekbarProgressIsMax() { - mWindowMagnificationSettings.setMagnificationScale(8f); + mWindowMagnificationSettings.setMagnificationScale(SCALE_MAX_VALUE); setupMagnificationCapabilityAndMode( /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mWindowMagnificationSettings.showSettingPanel(); - // 8.0f is max magnification {@link MagnificationScaleProvider#MAX_SCALE}. - // Max zoom seek bar is 70. - assertThat(mZoomSeekbar.getProgress()).isEqualTo(70); + assertThat(mZoomSeekbar.getProgress()).isEqualTo(getSeekBarMax()); } @Test public void seekbarProgress_aboveMaxMagnificationBefore_seekbarProgressIsMax() { - mWindowMagnificationSettings.setMagnificationScale(9f); + mWindowMagnificationSettings.setMagnificationScale(SCALE_MAX_VALUE + 1f); setupMagnificationCapabilityAndMode( /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mWindowMagnificationSettings.showSettingPanel(); - // Max zoom seek bar is 70. - assertThat(mZoomSeekbar.getProgress()).isEqualTo(70); + assertThat(mZoomSeekbar.getProgress()).isEqualTo(getSeekBarMax()); } @Test @@ -589,4 +589,11 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase { anyInt(), eq(UserHandle.USER_CURRENT))).thenReturn(mode); } + + private int getSeekBarMax() { + // Calculates the maximum index (or positions) the seekbar can have. + // This is achieved by multiplying the range of possible scales with the magnitude of + // change per each movement on the seekbar. + return (int) ((SCALE_MAX_VALUE - SCALE_MIN_VALUE) * mZoomSeekbar.getChangeMagnitude()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java index 5ff3915c76f9..113a8c05ee66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java @@ -45,6 +45,7 @@ import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.AccessibilityButtonModeObserver; import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.util.settings.SecureSettings; @@ -90,6 +91,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { private SecureSettings mSecureSettings; @Mock private Lazy<ViewCapture> mLazyViewCapture; + @Mock + private NavigationModeController mNavigationModeController; @Before public void setUp() throws Exception { @@ -163,7 +166,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { enableAccessibilityFloatingMenuConfig(); mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, - mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings); + mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, + mNavigationModeController); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserUnlocked(); @@ -190,7 +194,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { enableAccessibilityFloatingMenuConfig(); mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, - mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings); + mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, + mNavigationModeController); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserSwitching(fakeUserId); @@ -204,7 +209,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { enableAccessibilityFloatingMenuConfig(); mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, - mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings); + mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, + mNavigationModeController); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserUnlocked(); mKeyguardCallback.onKeyguardVisibilityChanged(true); @@ -340,7 +346,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { new AccessibilityFloatingMenuController(mContextWrapper, windowManager, viewCaptureAwareWindowManager, displayManager, mAccessibilityManager, mTargetsObserver, mModeObserver, mKeyguardUpdateMonitor, mSecureSettings, - displayTracker); + displayTracker, mNavigationModeController); controller.init(); return controller; diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java index 19b27003ebd1..d7acaaf796f8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java @@ -34,7 +34,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.utils.TestUtils; import com.android.systemui.util.settings.SecureSettings; import com.android.wm.shell.common.bubbles.DismissView; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import org.junit.Before; import org.junit.Rule; diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java index c5509ac44046..157cccc3d62f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java @@ -44,6 +44,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.utils.TestUtils; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.res.R; import com.android.systemui.util.settings.SecureSettings; @@ -94,7 +95,8 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { mMenuViewLayer = spy(new MenuViewLayer( mContext, stubWindowManager, mAccessibilityManager, stubMenuViewModel, stubMenuViewAppearance, mMenuView, - mock(IAccessibilityFloatingMenu.class), mSecureSettings)); + mock(IAccessibilityFloatingMenu.class), mSecureSettings, + mock(NavigationModeController.class))); doNothing().when(mMenuViewLayer).gotoEditScreen(); doReturn(mDraggableBounds).when(mMenuView).getMenuDraggableBounds(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java index 07ce7b9352c1..fcdeff9ab683 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java @@ -21,6 +21,7 @@ import static android.view.WindowInsets.Type.systemBars; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -41,6 +42,7 @@ import androidx.test.filters.SmallTest; import com.android.app.viewcapture.ViewCapture; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.systemui.SysuiTestCase; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.util.settings.SecureSettings; import kotlin.Lazy; @@ -90,7 +92,8 @@ public class MenuViewLayerControllerTest extends SysuiTestCase { when(mWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, 1080, 2340)); when(mWindowMetrics.getWindowInsets()).thenReturn(stubDisplayInsets()); mMenuViewLayerController = new MenuViewLayerController(mContext, mWindowManager, - viewCaptureAwareWm, mAccessibilityManager, mSecureSettings); + viewCaptureAwareWm, mAccessibilityManager, mSecureSettings, + mock(NavigationModeController.class)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java index 12140b58936b..c451c32c4587 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java @@ -81,9 +81,10 @@ import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestableContext; import com.android.systemui.accessibility.utils.TestUtils; +import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.res.R; import com.android.systemui.util.settings.SecureSettings; -import com.android.wm.shell.common.magnetictarget.MagnetizedObject; +import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import org.junit.After; import org.junit.Before; @@ -169,7 +170,7 @@ public class MenuViewLayerTest extends SysuiTestCase { mMenuViewLayer = spy(new MenuViewLayer(mSpyContext, mStubWindowManager, mStubAccessibilityManager, mMenuViewModel, menuViewAppearance, mMenuView, - mFloatingMenu, mSecureSettings)); + mFloatingMenu, mSecureSettings, mock(NavigationModeController.class))); mMenuAnimationController = mMenuView.getMenuAnimationController(); doNothing().when(mSpyContext).startActivity(any()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt new file mode 100644 index 000000000000..969e26a8d884 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bluetooth.qsdialog + +import com.android.systemui.bluetooth.bluetoothAdapter +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher +import org.mockito.kotlin.mock + +val Kosmos.deviceItemInteractor: DeviceItemInteractor by + Kosmos.Fixture { mock<DeviceItemInteractor>() } + +val Kosmos.bluetoothDeviceMetadataInteractor by + Kosmos.Fixture { + BluetoothDeviceMetadataInteractor( + deviceItemInteractor, + bluetoothAdapter, + bluetoothTileDialogLogger, + fakeExecutor, + testDispatcher, + ) + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt new file mode 100644 index 000000000000..f06b105a9e26 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bluetooth.qsdialog + +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothDevice +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.systemui.SysuiTestCase +import com.android.systemui.bluetooth.bluetoothAdapter +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.never +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +@SmallTest +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class BluetoothDeviceMetadataInteractorTest : SysuiTestCase() { + @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() + + private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() } + + private val deviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow() + @Mock private lateinit var cachedDevice1: CachedBluetoothDevice + @Mock private lateinit var bluetoothDevice1: BluetoothDevice + @Mock private lateinit var cachedDevice2: CachedBluetoothDevice + @Mock private lateinit var bluetoothDevice2: BluetoothDevice + @Captor + private lateinit var argumentCaptor: ArgumentCaptor<BluetoothAdapter.OnMetadataChangedListener> + private lateinit var interactor: BluetoothDeviceMetadataInteractor + + @Before + fun setUp() { + with(kosmos) { + whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(deviceItemUpdate) + + whenever(cachedDevice1.device).thenReturn(bluetoothDevice1) + whenever(cachedDevice1.name).thenReturn(DEVICE_NAME) + whenever(cachedDevice1.address).thenReturn(DEVICE_ADDRESS) + whenever(cachedDevice1.connectionSummary).thenReturn(CONNECTION_SUMMARY) + whenever(bluetoothDevice1.address).thenReturn(DEVICE_ADDRESS) + + whenever(cachedDevice2.device).thenReturn(bluetoothDevice2) + whenever(cachedDevice2.name).thenReturn(DEVICE_NAME) + whenever(cachedDevice2.address).thenReturn(DEVICE_ADDRESS) + whenever(cachedDevice2.connectionSummary).thenReturn(CONNECTION_SUMMARY) + whenever(bluetoothDevice2.address).thenReturn(DEVICE_ADDRESS) + + interactor = bluetoothDeviceMetadataInteractor + } + } + + @Test + fun deviceItemUpdateEmpty_doNothing() { + with(kosmos) { + testScope.runTest { + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(emptyList()) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter, never()).addOnMetadataChangedListener(any(), any(), any()) + verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any()) + } + } + } + + @Test + fun deviceItemUpdate_registerListener() { + with(kosmos) { + testScope.runTest { + val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1) + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter) + .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any()) + verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any()) + } + } + } + + @Test + fun deviceItemUpdate_sameDeviceItems_registerListenerOnce() { + with(kosmos) { + testScope.runTest { + val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1) + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(listOf(deviceItem)) + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter) + .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any()) + verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any()) + } + } + } + + @Test + fun deviceItemUpdate_differentDeviceItems_unregisterOldAndRegisterNew() { + with(kosmos) { + testScope.runTest { + val deviceItem1 = AvailableMediaDeviceItemFactory().create(context, cachedDevice1) + val deviceItem2 = AvailableMediaDeviceItemFactory().create(context, cachedDevice2) + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(listOf(deviceItem1)) + deviceItemUpdate.emit(listOf(deviceItem1, deviceItem2)) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter, times(2)) + .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any()) + verify(bluetoothAdapter) + .addOnMetadataChangedListener(eq(bluetoothDevice2), any(), any()) + verify(bluetoothAdapter) + .removeOnMetadataChangedListener(eq(bluetoothDevice1), any()) + } + } + } + + @Test + fun metadataUpdate_triggerCallback_emit() { + with(kosmos) { + testScope.runTest { + val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1) + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter) + .addOnMetadataChangedListener( + eq(bluetoothDevice1), + any(), + argumentCaptor.capture() + ) + + val listener = argumentCaptor.value + listener.onMetadataChanged( + bluetoothDevice1, + BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY, + ByteArray(0) + ) + assertThat(update).isEqualTo(Unit) + } + } + } + + @Test + fun metadataUpdate_triggerCallbackNonBatteryKey_doNothing() { + with(kosmos) { + testScope.runTest { + val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1) + val update by collectLastValue(interactor.metadataUpdate) + deviceItemUpdate.emit(listOf(deviceItem)) + runCurrent() + + assertThat(update).isNull() + verify(bluetoothAdapter) + .addOnMetadataChangedListener( + eq(bluetoothDevice1), + any(), + argumentCaptor.capture() + ) + + val listener = argumentCaptor.value + listener.onMetadataChanged( + bluetoothDevice1, + BluetoothDevice.METADATA_MODEL_NAME, + ByteArray(0) + ) + + assertThat(update).isNull() + } + } + } + + companion object { + private const val DEVICE_NAME = "DeviceName" + private const val CONNECTION_SUMMARY = "ConnectionSummary" + private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C" + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt index 9abb85d249eb..d7bea6680c2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt @@ -77,6 +77,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { @Mock private lateinit var audioSharingInteractor: AudioSharingInteractor + @Mock private lateinit var bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor + @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor @Mock private lateinit var deviceItemActionInteractor: DeviceItemActionInteractor @@ -138,6 +140,7 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { ) ), audioSharingInteractor, + bluetoothDeviceMetadataInteractor, mDialogTransitionAnimator, activityStarter, uiEventLogger, @@ -150,6 +153,8 @@ class BluetoothTileDialogViewModelTest : SysuiTestCase() { whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow()) whenever(deviceItemInteractor.deviceItemUpdateRequest) .thenReturn(MutableStateFlow(Unit).asStateFlow()) + whenever(deviceItemInteractor.showSeeAllUpdate).thenReturn(getMutableStateFlow(false)) + whenever(bluetoothDeviceMetadataInteractor.metadataUpdate).thenReturn(MutableSharedFlow()) whenever(mBluetoothTileDialogDelegateDelegateFactory.create(any(), anyInt(), any(), any())) .thenReturn(bluetoothTileDialogDelegate) whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog) diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt index 7f7abaf9b689..194590c1f626 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt @@ -113,9 +113,11 @@ class DeviceItemInteractorTest : SysuiTestCase() { ) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(emptyList<DeviceItem>()) + assertThat(latestShowSeeAll).isFalse() } } @@ -128,9 +130,11 @@ class DeviceItemInteractorTest : SysuiTestCase() { ) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(emptyList<DeviceItem>()) + assertThat(latestShowSeeAll).isFalse() } } @@ -143,9 +147,11 @@ class DeviceItemInteractorTest : SysuiTestCase() { ) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(listOf(deviceItem1)) + assertThat(latestShowSeeAll).isFalse() } } @@ -158,9 +164,11 @@ class DeviceItemInteractorTest : SysuiTestCase() { ) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2)) + assertThat(latestShowSeeAll).isFalse() } } @@ -184,9 +192,11 @@ class DeviceItemInteractorTest : SysuiTestCase() { `when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1)) + assertThat(latestShowSeeAll).isFalse() } } @@ -207,9 +217,30 @@ class DeviceItemInteractorTest : SysuiTestCase() { `when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE) val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1)) + assertThat(latestShowSeeAll).isFalse() + } + } + + @Test + fun testUpdateDeviceItems_showMaxDeviceItems_showSeeAll() { + testScope.runTest { + `when`(bluetoothTileDialogRepository.cachedDevices) + .thenReturn(listOf(cachedDevice2, cachedDevice2, cachedDevice2, cachedDevice2)) + `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null) + interactor.setDeviceItemFactoryListForTesting( + listOf(createFactory({ true }, deviceItem2)) + ) + + val latest by collectLastValue(interactor.deviceItemUpdate) + val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate) + interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD) + + assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2, deviceItem2)) + assertThat(latestShowSeeAll).isTrue() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt index a4936e63df8f..8e215f994e4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt @@ -33,9 +33,10 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout -import com.android.systemui.bouncer.ui.viewmodel.bouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModelFactory import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.motion.createSysUiComposeMotionTestRule import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.testKosmos @@ -81,7 +82,8 @@ class BouncerContentTest : SysuiTestCase() { private fun BouncerContentUnderTest() { PlatformTheme { BouncerContent( - viewModel = kosmos.bouncerViewModel, + viewModel = + rememberViewModel { kosmos.bouncerSceneContentViewModelFactory.create() }, layout = BouncerSceneLayout.BESIDE_USER_SWITCHER, modifier = Modifier.fillMaxSize().testTag("BouncerContent"), dialogFactory = bouncerDialogFactory diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt index 2948c0274525..4b61a0d02f1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt @@ -24,14 +24,14 @@ import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import com.android.systemui.SysuiTestCase -import com.android.systemui.bouncer.domain.interactor.bouncerInteractor -import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel -import com.android.systemui.kosmos.testScope +import com.android.systemui.bouncer.ui.viewmodel.patternBouncerViewModelFactory +import com.android.systemui.lifecycle.activateIn import com.android.systemui.motion.createSysUiComposeMotionTestRule import com.android.systemui.testKosmos import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.takeWhile +import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -51,15 +51,15 @@ class PatternBouncerTest : SysuiTestCase() { @get:Rule val motionTestRule = createSysUiComposeMotionTestRule(kosmos) - private val bouncerInteractor by lazy { kosmos.bouncerInteractor } - private val viewModel by lazy { - PatternBouncerViewModel( - applicationContext = context, - viewModelScope = kosmos.testScope.backgroundScope, - interactor = bouncerInteractor, + private val viewModel = + kosmos.patternBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true).asStateFlow(), onIntentionalUserInput = {}, ) + + @Before + fun setUp() { + viewModel.activateIn(motionTestRule.toolkit.testScope) } @Composable diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt index e4f0910f99fd..f1782e8b0569 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt @@ -31,11 +31,11 @@ import android.service.controls.ControlsProviderService import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.applications.ServiceListing -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags +import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.util.ActivityTaskManagerProxy import com.android.systemui.util.concurrency.FakeExecutor @@ -45,6 +45,8 @@ import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import java.io.PrintWriter +import java.util.concurrent.CountDownLatch import java.util.concurrent.Executor import org.junit.After import org.junit.Assert.assertEquals @@ -56,39 +58,33 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatcher import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.inOrder import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations +import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) class ControlsListingControllerImplTest : SysuiTestCase() { companion object { - private const val FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or + private const val FLAGS = + PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() } - @Mock - private lateinit var mockSL: ServiceListing - @Mock - private lateinit var mockCallback: ControlsListingController.ControlsListingCallback - @Mock - private lateinit var mockCallbackOther: ControlsListingController.ControlsListingCallback - @Mock(stubOnly = true) - private lateinit var userTracker: UserTracker - @Mock(stubOnly = true) - private lateinit var dumpManager: DumpManager - @Mock - private lateinit var packageManager: PackageManager - @Mock - private lateinit var featureFlags: FeatureFlags - @Mock - private lateinit var activityTaskManagerProxy: ActivityTaskManagerProxy + @Mock private lateinit var mockSL: ServiceListing + @Mock private lateinit var mockCallback: ControlsListingController.ControlsListingCallback + @Mock private lateinit var mockCallbackOther: ControlsListingController.ControlsListingCallback + @Mock(stubOnly = true) private lateinit var userTracker: UserTracker + @Mock(stubOnly = true) private lateinit var dumpManager: DumpManager + @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var featureFlags: FeatureFlags + @Mock private lateinit var activityTaskManagerProxy: ActivityTaskManagerProxy private var componentName = ComponentName("pkg", "class1") private var activityName = ComponentName("pkg", "activity") @@ -98,7 +94,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { private lateinit var controller: ControlsListingControllerImpl private var serviceListingCallbackCaptor = - ArgumentCaptor.forClass(ServiceListing.Callback::class.java) + ArgumentCaptor.forClass(ServiceListing.Callback::class.java) private val user = mContext.userId private val otherUser = user + 1 @@ -112,23 +108,24 @@ class ControlsListingControllerImplTest : SysuiTestCase() { `when`(userTracker.userContext).thenReturn(context) // Return disabled by default `when`(packageManager.getComponentEnabledSetting(any())) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED) `when`(activityTaskManagerProxy.supportsMultiWindow(any())).thenReturn(true) mContext.setMockPackageManager(packageManager) - mContext.orCreateTestableResources - .addOverride( - R.array.config_controlsPreferredPackages, - arrayOf(componentName.packageName) - ) + mContext.orCreateTestableResources.addOverride( + R.array.config_controlsPreferredPackages, + arrayOf(componentName.packageName) + ) - val wrapper = object : ContextWrapper(mContext) { - override fun createContextAsUser(user: UserHandle, flags: Int): Context { - return baseContext + val wrapper = + object : ContextWrapper(mContext) { + override fun createContextAsUser(user: UserHandle, flags: Int): Context { + return baseContext + } } - } - controller = ControlsListingControllerImpl( + controller = + ControlsListingControllerImpl( wrapper, executor, { mockSL }, @@ -136,7 +133,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { activityTaskManagerProxy, dumpManager, featureFlags - ) + ) verify(mockSL).addCallback(capture(serviceListingCallbackCaptor)) } @@ -165,13 +162,13 @@ class ControlsListingControllerImplTest : SysuiTestCase() { callback?.onServicesReloaded(listOf(ServiceInfo(componentName))) } ControlsListingControllerImpl( - mContext, - exec, - { mockServiceListing }, - userTracker, - activityTaskManagerProxy, - dumpManager, - featureFlags + mContext, + exec, + { mockServiceListing }, + userTracker, + activityTaskManagerProxy, + dumpManager, + featureFlags ) } @@ -201,8 +198,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Suppress("unchecked_cast") val captor: ArgumentCaptor<List<ControlsServiceInfo>> = - ArgumentCaptor.forClass(List::class.java) - as ArgumentCaptor<List<ControlsServiceInfo>> + ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<ControlsServiceInfo>> executor.runAllReady() reset(mockCallback) @@ -242,8 +238,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Suppress("unchecked_cast") val captor: ArgumentCaptor<List<ControlsServiceInfo>> = - ArgumentCaptor.forClass(List::class.java) - as ArgumentCaptor<List<ControlsServiceInfo>> + ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<ControlsServiceInfo>> executor.runAllReady() reset(mockCallback) @@ -285,10 +280,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testNoActivity_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -300,10 +292,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityWithoutPermission_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) setUpQueryResult(listOf(ActivityInfo(activityName))) @@ -317,14 +306,11 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityPermissionNotExported_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) - setUpQueryResult(listOf( - ActivityInfo(activityName, permission = Manifest.permission.BIND_CONTROLS) - )) + setUpQueryResult( + listOf(ActivityInfo(activityName, permission = Manifest.permission.BIND_CONTROLS)) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -336,18 +322,17 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityDisabled_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -359,21 +344,20 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityEnabled_correctPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) `when`(packageManager.getComponentEnabledSetting(eq(activityName))) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -385,22 +369,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityDefaultEnabled_correctPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) `when`(packageManager.getComponentEnabledSetting(eq(activityName))) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - enabled = true, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + enabled = true, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -412,22 +395,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityDefaultDisabled_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) `when`(packageManager.getComponentEnabledSetting(eq(activityName))) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - enabled = false, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + enabled = false, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -439,22 +421,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testActivityDifferentPackage_nullPanel() { - val serviceInfo = ServiceInfo( - componentName, - ComponentName("other_package", "cls") - ) + val serviceInfo = ServiceInfo(componentName, ComponentName("other_package", "cls")) `when`(packageManager.getComponentEnabledSetting(eq(activityName))) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - enabled = true, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + enabled = true, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -466,24 +447,25 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Test fun testPackageNotPreferred_correctPanel() { - mContext.orCreateTestableResources - .addOverride(R.array.config_controlsPreferredPackages, arrayOf<String>()) - - val serviceInfo = ServiceInfo( - componentName, - activityName + mContext.orCreateTestableResources.addOverride( + R.array.config_controlsPreferredPackages, + arrayOf<String>() ) + val serviceInfo = ServiceInfo(componentName, activityName) + `when`(packageManager.getComponentEnabledSetting(eq(activityName))) - .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED) + .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED) - setUpQueryResult(listOf( + setUpQueryResult( + listOf( ActivityInfo( - activityName, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + activityName, + exported = true, + permission = Manifest.permission.BIND_CONTROLS ) - )) + ) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -512,16 +494,19 @@ class ControlsListingControllerImplTest : SysuiTestCase() { `when`(userTracker.userHandle).thenReturn(UserHandle.of(user)) controller.forceReload() - verify(packageManager).queryIntentServicesAsUser( + verify(packageManager) + .queryIntentServicesAsUser( argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)), - argThat(FlagsMatcher( + argThat( + FlagsMatcher( PackageManager.GET_META_DATA.toLong() or - PackageManager.GET_SERVICES.toLong() or - PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or - PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() - )), + PackageManager.GET_SERVICES.toLong() or + PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or + PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() + ) + ), eq(UserHandle.of(user)) - ) + ) } @Test @@ -529,16 +514,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { val resolveInfo = ResolveInfo() resolveInfo.serviceInfo = ServiceInfo(componentName) - `when`(packageManager.queryIntentServicesAsUser( - argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)), - argThat(FlagsMatcher( - PackageManager.GET_META_DATA.toLong() or + `when`( + packageManager.queryIntentServicesAsUser( + argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)), + argThat( + FlagsMatcher( + PackageManager.GET_META_DATA.toLong() or PackageManager.GET_SERVICES.toLong() or PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() - )), - any<UserHandle>() - )).thenReturn(listOf(resolveInfo)) + ) + ), + any<UserHandle>() + ) + ) + .thenReturn(listOf(resolveInfo)) controller.forceReload() @@ -554,17 +544,19 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Suppress("unchecked_cast") val captor: ArgumentCaptor<List<ControlsServiceInfo>> = - ArgumentCaptor.forClass(List::class.java) - as ArgumentCaptor<List<ControlsServiceInfo>> + ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<ControlsServiceInfo>> val resolveInfo = ResolveInfo() resolveInfo.serviceInfo = ServiceInfo(componentName) - `when`(packageManager.queryIntentServicesAsUser( - any(), - any<PackageManager.ResolveInfoFlags>(), - any<UserHandle>() - )).thenReturn(listOf(resolveInfo)) + `when`( + packageManager.queryIntentServicesAsUser( + any(), + any<PackageManager.ResolveInfoFlags>(), + any<UserHandle>() + ) + ) + .thenReturn(listOf(resolveInfo)) reset(mockCallback) controller.forceReload() @@ -581,22 +573,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { fun testNoPanelIfMultiWindowNotSupported() { `when`(activityTaskManagerProxy.supportsMultiWindow(any())).thenReturn(false) - val serviceInfo = ServiceInfo( - componentName, - activityName - ) + val serviceInfo = ServiceInfo(componentName, activityName) `when`(packageManager.getComponentEnabledSetting(eq(activityName))) .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - setUpQueryResult(listOf( - ActivityInfo( - activityName, - enabled = true, - exported = true, - permission = Manifest.permission.BIND_CONTROLS + setUpQueryResult( + listOf( + ActivityInfo( + activityName, + enabled = true, + exported = true, + permission = Manifest.permission.BIND_CONTROLS + ) ) - )) + ) val list = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(list) @@ -606,20 +597,77 @@ class ControlsListingControllerImplTest : SysuiTestCase() { assertNull(controller.getCurrentServices()[0].panelActivity) } + @Test + fun dumpAndAddRemoveCallback_willNotThrowConcurrentModificationException() { + val repeat = 100 + controller.addCallback(mockCallback) // 1 extra callback increases the duration of iteration + + // the goal of these two barriers is to make the modify and iterate run concurrently + val startSignal = CountDownLatch(2) + val doneSignal = CountDownLatch(2) + val modifyRunnable = Runnable { + for (i in 1..repeat) { + controller.addCallback(mockCallbackOther) + executor.runAllReady() + controller.removeCallback(mockCallbackOther) + executor.runAllReady() + } + } + val printWriter = mock<PrintWriter>() + val arr = arrayOf<String>() + val iterateRunnable = Runnable { + for (i in 1..repeat) { + controller.dump(printWriter, arr) + } + } + + val workerThread = Thread(Worker(startSignal, doneSignal, modifyRunnable)) + workerThread.start() + val workerThreadOther = Thread(Worker(startSignal, doneSignal, iterateRunnable)) + workerThreadOther.start() + doneSignal.await() + workerThread.interrupt() + workerThreadOther.interrupt() + } + + class Worker : Runnable { + private val startSignal: CountDownLatch + private val doneSignal: CountDownLatch + private val runnable: Runnable + + constructor(start: CountDownLatch, done: CountDownLatch, run: Runnable) { + startSignal = start + doneSignal = done + runnable = run + } + + override fun run() { + try { + startSignal.countDown() + startSignal.await() + runnable.run() + doneSignal.countDown() + } catch (ex: InterruptedException) { + return + } + } + } + private fun ServiceInfo( - componentName: ComponentName, - panelActivityComponentName: ComponentName? = null + componentName: ComponentName, + panelActivityComponentName: ComponentName? = null ): ServiceInfo { return ServiceInfo().apply { packageName = componentName.packageName name = componentName.className panelActivityComponentName?.let { - metaData = Bundle().apply { - putString( + metaData = + Bundle().apply { + putString( ControlsProviderService.META_DATA_PANEL_ACTIVITY, it.flattenToShortString() - ) - } + ) + } } } } @@ -642,34 +690,29 @@ class ControlsListingControllerImplTest : SysuiTestCase() { private fun setUpQueryResult(infos: List<ActivityInfo>) { `when`( packageManager.queryIntentActivitiesAsUser( - argThat(IntentMatcherComponent(activityName)), - argThat(FlagsMatcher(FLAGS)), - eq(UserHandle.of(user)) + argThat(IntentMatcherComponent(activityName)), + argThat(FlagsMatcher(FLAGS)), + eq(UserHandle.of(user)) ) - ).thenReturn(infos.map { - ResolveInfo().apply { activityInfo = it } - }) + ) + .thenReturn(infos.map { ResolveInfo().apply { activityInfo = it } }) } - private class IntentMatcherComponent( - private val componentName: ComponentName - ) : ArgumentMatcher<Intent> { + private class IntentMatcherComponent(private val componentName: ComponentName) : + ArgumentMatcher<Intent> { override fun matches(argument: Intent?): Boolean { return argument?.component == componentName } } - private class IntentMatcherAction( - private val action: String - ) : ArgumentMatcher<Intent> { + private class IntentMatcherAction(private val action: String) : ArgumentMatcher<Intent> { override fun matches(argument: Intent?): Boolean { return argument?.action == action } } - private class FlagsMatcher( - private val flags: Long - ) : ArgumentMatcher<PackageManager.ResolveInfoFlags> { + private class FlagsMatcher(private val flags: Long) : + ArgumentMatcher<PackageManager.ResolveInfoFlags> { override fun matches(argument: PackageManager.ResolveInfoFlags?): Boolean { return flags == argument?.value } diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt index fd9964f938c8..a2b50fd2ec17 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt @@ -17,8 +17,6 @@ package com.android.systemui.display.domain.interactor import android.companion.virtual.VirtualDeviceManager -import android.companion.virtual.flags.Flags.FLAG_INTERACTIVE_SCREEN_MIRROR -import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper import android.view.Display import android.view.Display.TYPE_EXTERNAL @@ -160,7 +158,6 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { } @Test - @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR) fun displayState_virtualDeviceOwnedMirrorVirtualDisplay_connected() = testScope.runTest { whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt())) @@ -183,7 +180,6 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { } @Test - @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR) fun virtualDeviceOwnedMirrorVirtualDisplay_emitsConnectedDisplayAddition() = testScope.runTest { whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt())) diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt new file mode 100644 index 000000000000..1d96c4d67c77 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.data.repository + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD +import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD +import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.google.common.truth.Truth.assertThat +import java.time.Instant +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class TutorialSchedulerRepositoryTest : SysuiTestCase() { + + private lateinit var underTest: TutorialSchedulerRepository + private val kosmos = Kosmos() + private val testScope = kosmos.testScope + + @Before + fun setup() { + underTest = + TutorialSchedulerRepository( + context, + testScope.backgroundScope, + "TutorialSchedulerRepositoryTest" + ) + } + + @After + fun clear() { + testScope.launch { underTest.clearDataStore() } + } + + @Test + fun initialState() = + testScope.runTest { + assertThat(underTest.wasEverConnected(KEYBOARD)).isFalse() + assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse() + assertThat(underTest.isLaunched(KEYBOARD)).isFalse() + assertThat(underTest.isLaunched(TOUCHPAD)).isFalse() + } + + @Test + fun connectKeyboard() = + testScope.runTest { + val now = Instant.now() + underTest.updateFirstConnectionTime(KEYBOARD, now) + + assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue() + assertThat(underTest.firstConnectionTime(KEYBOARD)!!.epochSecond) + .isEqualTo(now.epochSecond) + assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse() + } + + @Test + fun launchKeyboard() = + testScope.runTest { + val now = Instant.now() + underTest.updateLaunchTime(KEYBOARD, now) + + assertThat(underTest.isLaunched(KEYBOARD)).isTrue() + assertThat(underTest.launchTime(KEYBOARD)!!.epochSecond).isEqualTo(now.epochSecond) + assertThat(underTest.isLaunched(TOUCHPAD)).isFalse() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt new file mode 100644 index 000000000000..0c716137f434 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.inputdevice.tutorial.ui.viewmodel + +import androidx.lifecycle.Lifecycle.Event +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.SavedStateHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues +import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE +import com.android.systemui.keyboard.data.repository.keyboardRepository +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.model.sysUiState +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED +import com.android.systemui.testKosmos +import com.android.systemui.touchpad.data.repository.TouchpadRepository +import com.android.systemui.touchpad.tutorial.touchpadGesturesInteractor +import com.android.systemui.util.coroutines.MainDispatcherRule +import com.google.common.truth.Truth.assertThat +import java.util.Optional +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val sysUiState = kosmos.sysUiState + private val touchpadRepo = PrettyFakeTouchpadRepository() + private val keyboardRepo = kosmos.keyboardRepository + private var startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + private val viewModel by lazy { createViewModel(startingPeripheral) } + + // createUnsafe so its methods don't have to be called on Main thread + private val lifecycle = LifecycleRegistry.createUnsafe(mock(LifecycleOwner::class.java)) + + @get:Rule val mainDispatcherRule = MainDispatcherRule(kosmos.testDispatcher) + + private fun createViewModel( + startingPeripheral: String = INTENT_TUTORIAL_TYPE_TOUCHPAD, + hasTouchpadTutorialScreens: Boolean = true, + ): KeyboardTouchpadTutorialViewModel { + val viewModel = + KeyboardTouchpadTutorialViewModel( + Optional.of(kosmos.touchpadGesturesInteractor), + KeyboardTouchpadConnectionInteractor(keyboardRepo, touchpadRepo), + hasTouchpadTutorialScreens, + SavedStateHandle(mapOf(INTENT_TUTORIAL_TYPE_KEY to startingPeripheral)) + ) + lifecycle.addObserver(viewModel) + return viewModel + } + + @Test + fun screensOrder_whenTouchpadAndKeyboardConnected() = + testScope.runTest { + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true, touchpadConnected = true) + + goToNextScreen() + goToNextScreen() + // reached the last screen + + assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY).inOrder() + assertThat(closeActivity).isFalse() + } + + @Test + fun screensOrder_whenKeyboardDisconnectsDuringTutorial() = + testScope.runTest { + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true, touchpadConnected = true) + + // back gesture screen + goToNextScreen() + // home gesture screen + peripheralsState(keyboardConnected = false, touchpadConnected = true) + goToNextScreen() + // no action key screen because keyboard disconnected + + assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrderUntilFinish_whenTouchpadAndKeyboardConnected() = + testScope.runTest { + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + + peripheralsState(keyboardConnected = true, touchpadConnected = true) + + goToNextScreen() + goToNextScreen() + // we're at the last screen so "next screen" should be actually closing activity + goToNextScreen() + + assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_whenGoingBackToPreviousScreens() = + testScope.runTest { + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true, touchpadConnected = true) + + // back gesture + goToNextScreen() + // home gesture + goToNextScreen() + // action key + + goBack() + // home gesture + goBack() + // back gesture + goBack() + // finish activity + + assertThat(screens) + .containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY, HOME_GESTURE, BACK_GESTURE) + .inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_whenGoingBackAndOnlyKeyboardConnected() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true, touchpadConnected = false) + + // action key screen + goBack() + // activity finished + + assertThat(screens).containsExactly(ACTION_KEY).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_whenTouchpadConnected() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + + peripheralsState(keyboardConnected = false, touchpadConnected = true) + + goToNextScreen() + goToNextScreen() + goToNextScreen() + + assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_whenKeyboardConnected() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + + peripheralsState(keyboardConnected = true) + + goToNextScreen() + goToNextScreen() + + assertThat(screens).containsExactly(ACTION_KEY).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun touchpadGesturesDisabled_onlyDuringTouchpadTutorial() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + collectValues(viewModel.screen) // just to initialize viewModel + peripheralsState(keyboardConnected = true, touchpadConnected = true) + + assertGesturesDisabled() + goToNextScreen() + goToNextScreen() + // end of touchpad tutorial, keyboard tutorial starts + assertGesturesNotDisabled() + } + + @Test + fun activityFinishes_ifTouchpadModuleIsNotPresent() = + testScope.runTest { + val viewModel = + createViewModel( + startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD, + hasTouchpadTutorialScreens = false + ) + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(touchpadConnected = true) + + assertThat(screens).isEmpty() + assertThat(closeActivity).isTrue() + } + + @Test + fun touchpadGesturesDisabled_whenTutorialGoesToForeground() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + collectValues(viewModel.screen) // just to initialize viewModel + peripheralsState(touchpadConnected = true) + + lifecycle.handleLifecycleEvent(Event.ON_START) + + assertGesturesDisabled() + } + + @Test + fun touchpadGesturesNotDisabled_whenTutorialGoesToBackground() = + testScope.runTest { + startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + collectValues(viewModel.screen) + peripheralsState(touchpadConnected = true) + + lifecycle.handleLifecycleEvent(Event.ON_START) + lifecycle.handleLifecycleEvent(Event.ON_STOP) + + assertGesturesNotDisabled() + } + + @Test + fun keyboardShortcutsDisabled_onlyDuringKeyboardTutorial() = + testScope.runTest { + // TODO(b/358587037) + } + + private fun TestScope.goToNextScreen() { + viewModel.onDoneButtonClicked() + runCurrent() + } + + private fun TestScope.goBack() { + viewModel.onBack() + runCurrent() + } + + private fun TestScope.peripheralsState( + keyboardConnected: Boolean = false, + touchpadConnected: Boolean = false + ) { + keyboardRepo.setIsAnyKeyboardConnected(keyboardConnected) + touchpadRepo.setIsAnyTouchpadConnected(touchpadConnected) + runCurrent() + } + + private fun TestScope.assertGesturesNotDisabled() = assertFlagEnabled(enabled = false) + + private fun TestScope.assertGesturesDisabled() = assertFlagEnabled(enabled = true) + + private fun TestScope.assertFlagEnabled(enabled: Boolean) { + // sysui state is changed on background scope so let's make sure it's executed + runCurrent() + assertThat(sysUiState.isFlagEnabled(SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED)) + .isEqualTo(enabled) + } + + // replace below when we have better fake + internal class PrettyFakeTouchpadRepository : TouchpadRepository { + + private val _isAnyTouchpadConnected = MutableStateFlow(false) + override val isAnyTouchpadConnected: Flow<Boolean> = _isAnyTouchpadConnected + + fun setIsAnyTouchpadConnected(connected: Boolean) { + _isAnyTouchpadConnected.value = connected + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt index 721162099169..f531a3fdd8f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/data/ShellRecentTaskListProviderTest.kt @@ -15,8 +15,8 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever -import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50 import com.android.wm.shell.recents.RecentTasks +import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50 import com.android.wm.shell.util.GroupedRecentTaskInfo import com.android.wm.shell.util.SplitBounds import com.google.common.truth.Truth.assertThat diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java deleted file mode 100644 index 1eeaef773689..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.qs; - -import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import android.content.BroadcastReceiver; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.UserHandle; -import android.provider.Settings.Secure; -import android.testing.TestableLooper.RunWithLooper; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.util.settings.FakeSettings; -import com.android.systemui.util.settings.SecureSettings; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import java.util.List; -import java.util.concurrent.Executor; - -@RunWith(AndroidJUnit4.class) -@RunWithLooper -@SmallTest -public class AutoAddTrackerTest extends SysuiTestCase { - - private static final int END_POSITION = -1; - private static final int USER = 0; - - @Mock - private BroadcastDispatcher mBroadcastDispatcher; - @Mock - private QSHost mQSHost; - @Mock - private DumpManager mDumpManager; - @Captor - private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor; - @Captor - private ArgumentCaptor<IntentFilter> mIntentFilterArgumentCaptor; - - private Executor mBackgroundExecutor = Runnable::run; // Direct executor - private AutoAddTracker mAutoTracker; - private SecureSettings mSecureSettings; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mSecureSettings = new FakeSettings(); - - mSecureSettings.putStringForUser(Secure.QS_AUTO_ADDED_TILES, null, USER); - - mAutoTracker = createAutoAddTracker(USER); - mAutoTracker.initialize(); - } - - @Test - public void testChangeFromBackup() { - assertFalse(mAutoTracker.isAdded(SAVER)); - - mSecureSettings.putStringForUser(Secure.QS_AUTO_ADDED_TILES, SAVER, USER); - - assertTrue(mAutoTracker.isAdded(SAVER)); - - mAutoTracker.destroy(); - } - - @Test - public void testSetAdded() { - assertFalse(mAutoTracker.isAdded(SAVER)); - mAutoTracker.setTileAdded(SAVER); - - assertTrue(mAutoTracker.isAdded(SAVER)); - - mAutoTracker.destroy(); - } - - @Test - public void testPersist() { - assertFalse(mAutoTracker.isAdded(SAVER)); - mAutoTracker.setTileAdded(SAVER); - - mAutoTracker.destroy(); - mAutoTracker = createAutoAddTracker(USER); - mAutoTracker.initialize(); - - assertTrue(mAutoTracker.isAdded(SAVER)); - - mAutoTracker.destroy(); - } - - @Test - public void testIndependentUsers() { - mAutoTracker.setTileAdded(SAVER); - - mAutoTracker = createAutoAddTracker(USER + 1); - mAutoTracker.initialize(); - assertFalse(mAutoTracker.isAdded(SAVER)); - } - - @Test - public void testChangeUser() { - mAutoTracker.setTileAdded(SAVER); - - mAutoTracker = createAutoAddTracker(USER + 1); - mAutoTracker.changeUser(UserHandle.of(USER)); - assertTrue(mAutoTracker.isAdded(SAVER)); - } - - @Test - public void testRestoredTilePositionPreserved() { - verify(mBroadcastDispatcher).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), anyInt(), any()); - String restoredTiles = "saver,internet,work,cast"; - Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, restoredTiles); - - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - assertEquals(2, mAutoTracker.getRestoredTilePosition("work")); - } - - @Test - public void testNoRestoredTileReturnsEndPosition() { - verify(mBroadcastDispatcher).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), anyInt(), any()); - Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, null); - - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - assertEquals(END_POSITION, mAutoTracker.getRestoredTilePosition("work")); - } - - @Test - public void testBroadcastReceiverRegistered() { - verify(mBroadcastDispatcher).registerReceiver( - any(), mIntentFilterArgumentCaptor.capture(), any(), eq(UserHandle.of(USER)), - anyInt(), any()); - - assertTrue( - mIntentFilterArgumentCaptor.getValue().hasAction(Intent.ACTION_SETTING_RESTORED)); - } - - @Test - public void testBroadcastReceiverChangesWithUser() { - mAutoTracker.changeUser(UserHandle.of(USER + 1)); - - InOrder inOrder = Mockito.inOrder(mBroadcastDispatcher); - inOrder.verify(mBroadcastDispatcher).unregisterReceiver(any()); - inOrder.verify(mBroadcastDispatcher) - .registerReceiver(any(), any(), any(), eq(UserHandle.of(USER + 1)), anyInt(), - any()); - } - - @Test - public void testSettingRestoredWithTilesNotRemovedInSource_noAutoAddedInTarget() { - verify(mBroadcastDispatcher).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), anyInt(), any()); - - // These tiles were present in the original device - String restoredTiles = "saver,work,internet,cast"; - Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, restoredTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - // And these tiles have been auto-added in the original device - // (no auto-added before restore) - String restoredAutoAddTiles = "work"; - Intent restoreAutoAddTilesIntent = - makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, null, restoredAutoAddTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent); - - // Then, don't remove any current tiles - verify(mQSHost, never()).removeTiles(any()); - assertEquals(restoredAutoAddTiles, - mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER)); - } - - @Test - public void testSettingRestoredWithTilesRemovedInSource_noAutoAddedInTarget() { - verify(mBroadcastDispatcher) - .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), - anyInt(), any()); - - // These tiles were present in the original device - String restoredTiles = "saver,internet,cast"; - Intent restoreTilesIntent = makeRestoreIntent(Secure.QS_TILES, null, restoredTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - // And these tiles have been auto-added in the original device - // (no auto-added before restore) - String restoredAutoAddTiles = "work"; - Intent restoreAutoAddTilesIntent = - makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, null, restoredAutoAddTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent); - - // Then, remove work tile - verify(mQSHost).removeTiles(List.of("work")); - assertEquals(restoredAutoAddTiles, - mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER)); - } - - @Test - public void testSettingRestoredWithTilesRemovedInSource_sameAutoAddedinTarget() { - verify(mBroadcastDispatcher) - .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), - anyInt(), any()); - - // These tiles were present in the original device - String restoredTiles = "saver,internet,cast"; - Intent restoreTilesIntent = - makeRestoreIntent(Secure.QS_TILES, "saver, internet, cast, work", restoredTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - // And these tiles have been auto-added in the original device - // (no auto-added before restore) - String restoredAutoAddTiles = "work"; - Intent restoreAutoAddTilesIntent = - makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, "work", restoredAutoAddTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent); - - // Then, remove work tile - verify(mQSHost).removeTiles(List.of("work")); - assertEquals(restoredAutoAddTiles, - mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER)); - } - - @Test - public void testSettingRestoredWithTilesRemovedInSource_othersAutoAddedinTarget() { - verify(mBroadcastDispatcher) - .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), - anyInt(), any()); - - // These tiles were present in the original device - String restoredTiles = "saver,internet,cast"; - Intent restoreTilesIntent = - makeRestoreIntent(Secure.QS_TILES, "saver, internet, cast, work", restoredTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreTilesIntent); - - // And these tiles have been auto-added in the original device - // (no auto-added before restore) - String restoredAutoAddTiles = "work"; - Intent restoreAutoAddTilesIntent = - makeRestoreIntent(Secure.QS_AUTO_ADDED_TILES, "inversion", restoredAutoAddTiles); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, restoreAutoAddTilesIntent); - - // Then, remove work tile - verify(mQSHost).removeTiles(List.of("work")); - - String setting = mSecureSettings.getStringForUser(Secure.QS_AUTO_ADDED_TILES, USER); - assertEquals(2, setting.split(",").length); - assertTrue(setting.contains("work")); - assertTrue(setting.contains("inversion")); - } - - - private Intent makeRestoreIntent( - String settingName, String previousValue, String restoredValue) { - Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED); - intent.putExtra(Intent.EXTRA_SETTING_NAME, settingName); - intent.putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, previousValue); - intent.putExtra(Intent.EXTRA_SETTING_NEW_VALUE, restoredValue); - return intent; - } - - private AutoAddTracker createAutoAddTracker(int user) { - // Null handler wil dispatch sync. - return new AutoAddTracker( - mSecureSettings, - mBroadcastDispatcher, - mQSHost, - mDumpManager, - null, - mBackgroundExecutor, - user - ); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java index 206bbbfba753..4ce2d7c6d78b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java @@ -51,6 +51,7 @@ import android.widget.FrameLayout; import androidx.compose.ui.platform.ComposeView; import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -611,7 +612,8 @@ public class QSImplTest extends SysuiTestCase { when(mQSContainerImplController.getView()).thenReturn(mContainer); when(mQSPanelController.getTileLayout()).thenReturn(mQQsTileLayout); when(mQuickQSPanelController.getTileLayout()).thenReturn(mQsTileLayout); - when(mFooterActionsViewModelFactory.create(any())).thenReturn(mFooterActionsViewModel); + when(mFooterActionsViewModelFactory.create(any(LifecycleOwner.class))) + .thenReturn(mFooterActionsViewModel); } private void setUpMedia() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java deleted file mode 100644 index 6d1bc824c3c1..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs; - - -import static com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE; -import static com.android.systemui.Flags.FLAG_QS_NEW_TILES; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.ContentObserver; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.util.SparseArray; - -import androidx.annotation.Nullable; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.util.CollectionUtils; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.animation.Expandable; -import com.android.systemui.classifier.FalsingManagerFake; -import com.android.systemui.dump.nano.SystemUIProtoDump; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.PluginManager; -import com.android.systemui.plugins.qs.QSFactory; -import com.android.systemui.plugins.qs.QSTile; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.qs.external.CustomTile; -import com.android.systemui.qs.external.CustomTileStatePersister; -import com.android.systemui.qs.external.TileLifecycleManager; -import com.android.systemui.qs.external.TileServiceKey; -import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository; -import com.android.systemui.qs.tileimpl.QSTileImpl; -import com.android.systemui.qs.tiles.di.NewQSTileFactory; -import com.android.systemui.res.R; -import com.android.systemui.settings.UserFileManager; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.shade.ShadeController; -import com.android.systemui.statusbar.phone.AutoTileManager; -import com.android.systemui.tuner.TunerService; -import com.android.systemui.util.FakeSharedPreferences; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.settings.FakeSettings; -import com.android.systemui.util.settings.SecureSettings; -import com.android.systemui.util.time.FakeSystemClock; - -import dagger.Lazy; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.stubbing.Answer; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.List; -import java.util.concurrent.Executor; - -import javax.inject.Provider; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class QSTileHostTest extends SysuiTestCase { - - private static String MOCK_STATE_STRING = "MockState"; - private static ComponentName CUSTOM_TILE = - ComponentName.unflattenFromString("TEST_PKG/.TEST_CLS"); - private static final String CUSTOM_TILE_SPEC = CustomTile.toSpec(CUSTOM_TILE); - private static final String SETTING = QSHost.TILES_SETTING; - @Mock - private PluginManager mPluginManager; - @Mock - private TunerService mTunerService; - @Mock - private AutoTileManager mAutoTiles; - @Mock - private ShadeController mShadeController; - @Mock - private QSLogger mQSLogger; - @Mock - private CustomTile mCustomTile; - @Mock - private UserTracker mUserTracker; - @Mock - private CustomTileStatePersister mCustomTileStatePersister; - @Mock - private TileLifecycleManager.Factory mTileLifecycleManagerFactory; - @Mock - private TileLifecycleManager mTileLifecycleManager; - @Mock - private UserFileManager mUserFileManager; - - private SecureSettings mSecureSettings; - - private QSFactory mDefaultFactory; - - private SparseArray<SharedPreferences> mSharedPreferencesByUser; - - private QSPipelineFlagsRepository mQSPipelineFlagsRepository; - - private FakeExecutor mMainExecutor; - - private QSTileHost mQSTileHost; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mSetFlagsRule.disableFlags(FLAG_QS_NEW_PIPELINE); - mSetFlagsRule.disableFlags(FLAG_QS_NEW_TILES); - mQSPipelineFlagsRepository = new QSPipelineFlagsRepository(); - - mMainExecutor = new FakeExecutor(new FakeSystemClock()); - - mSharedPreferencesByUser = new SparseArray<>(); - when(mTileLifecycleManagerFactory - .create(any(Intent.class), any(UserHandle.class))) - .thenReturn(mTileLifecycleManager); - when(mUserFileManager.getSharedPreferences(anyString(), anyInt(), anyInt())) - .thenAnswer((Answer<SharedPreferences>) invocation -> { - assertEquals(QSTileHost.TILES, invocation.getArgument(0)); - int userId = invocation.getArgument(2); - if (!mSharedPreferencesByUser.contains(userId)) { - mSharedPreferencesByUser.put(userId, new FakeSharedPreferences()); - } - return mSharedPreferencesByUser.get(userId); - }); - - mSecureSettings = new FakeSettings(); - saveSetting(""); - setUpTileFactory(); - mQSTileHost = new TestQSTileHost(mContext, () -> null, mDefaultFactory, mMainExecutor, - mPluginManager, mTunerService, () -> mAutoTiles, () -> mShadeController, - mQSLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister, - mTileLifecycleManagerFactory, mUserFileManager, mQSPipelineFlagsRepository); - mMainExecutor.runAllReady(); - - mSecureSettings.registerContentObserverForUserSync(SETTING, new ContentObserver(null) { - @Override - public void onChange(boolean selfChange) { - super.onChange(selfChange); - mMainExecutor.execute(() -> mQSTileHost.onTuningChanged(SETTING, getSetting())); - mMainExecutor.runAllReady(); - } - }, mUserTracker.getUserId()); - } - - private void saveSetting(String value) { - mSecureSettings.putStringForUser( - SETTING, value, "", false, mUserTracker.getUserId(), false); - } - - private String getSetting() { - return mSecureSettings.getStringForUser(SETTING, mUserTracker.getUserId()); - } - - private void setUpTileFactory() { - mDefaultFactory = new FakeQSFactory(spec -> { - if ("spec1".equals(spec)) { - return new TestTile1(mQSTileHost); - } else if ("spec2".equals(spec)) { - return new TestTile2(mQSTileHost); - } else if ("spec3".equals(spec)) { - return new TestTile3(mQSTileHost); - } else if ("na".equals(spec)) { - return new NotAvailableTile(mQSTileHost); - } else if (CUSTOM_TILE_SPEC.equals(spec)) { - QSTile tile = mCustomTile; - QSTile.State s = mock(QSTile.State.class); - s.spec = spec; - when(mCustomTile.getState()).thenReturn(s); - return tile; - } else if ("internet".equals(spec) - || "wifi".equals(spec) - || "cell".equals(spec)) { - return new TestTile1(mQSTileHost); - } else { - return null; - } - }); - when(mCustomTile.isAvailable()).thenReturn(true); - } - - @Test - public void testLoadTileSpecs_emptySetting() { - List<String> tiles = QSTileHost.loadTileSpecs(mContext, ""); - assertFalse(tiles.isEmpty()); - } - - @Test - public void testLoadTileSpecs_nullSetting() { - List<String> tiles = QSTileHost.loadTileSpecs(mContext, null); - assertFalse(tiles.isEmpty()); - } - - @Test - public void testInvalidSpecUsesDefault() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec2"); - saveSetting("not-valid"); - - assertEquals(2, mQSTileHost.getTiles().size()); - } - - @Test - public void testRemoveWifiAndCellularWithoutInternet() { - saveSetting("wifi, spec1, cell, spec2"); - - assertEquals("internet", mQSTileHost.getSpecs().get(0)); - assertEquals("spec1", mQSTileHost.getSpecs().get(1)); - assertEquals("spec2", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testRemoveWifiAndCellularWithInternet() { - saveSetting("wifi, spec1, cell, spec2, internet"); - - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec2", mQSTileHost.getSpecs().get(1)); - assertEquals("internet", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testRemoveWifiWithoutInternet() { - saveSetting("spec1, wifi, spec2"); - - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("internet", mQSTileHost.getSpecs().get(1)); - assertEquals("spec2", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testRemoveCellWithInternet() { - saveSetting("spec1, spec2, cell, internet"); - - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec2", mQSTileHost.getSpecs().get(1)); - assertEquals("internet", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testNoWifiNoCellularNoInternet() { - saveSetting("spec1,spec2"); - - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec2", mQSTileHost.getSpecs().get(1)); - } - - @Test - public void testSpecWithInvalidDoesNotUseDefault() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec2"); - saveSetting("spec2,not-valid"); - - assertEquals(1, mQSTileHost.getTiles().size()); - QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles()); - assertTrue(element instanceof TestTile2); - } - - @Test - public void testDump() { - saveSetting("spec1,spec2"); - StringWriter w = new StringWriter(); - PrintWriter pw = new PrintWriter(w); - mQSTileHost.dump(pw, new String[]{}); - - String output = "QSTileHost:" + "\n" - + "tile specs: [spec1, spec2]" + "\n" - + "current user: 0" + "\n" - + "is dirty: false" + "\n" - + "tiles:" + "\n" - + "TestTile1:" + "\n" - + " MockState" + "\n" - + "TestTile2:" + "\n" - + " MockState" + "\n"; - - System.out.println(output); - System.out.println(w.getBuffer().toString()); - - assertEquals(output, w.getBuffer().toString()); - } - - @Test - public void testDefault() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles_default, "spec1"); - saveSetting("default"); - assertEquals(1, mQSTileHost.getTiles().size()); - QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles()); - assertTrue(element instanceof TestTile1); - verify(mQSLogger).logTileAdded("spec1"); - } - - @Test - public void testNoRepeatedSpecs_addTile() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec2"); - saveSetting("spec1,spec2"); - - mQSTileHost.addTile("spec1"); - - assertEquals(2, mQSTileHost.getSpecs().size()); - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec2", mQSTileHost.getSpecs().get(1)); - } - - @Test - public void testAddTileAtValidPosition() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec3"); - saveSetting("spec1,spec3"); - - mQSTileHost.addTile("spec2", 1); - mMainExecutor.runAllReady(); - - assertEquals(3, mQSTileHost.getSpecs().size()); - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec2", mQSTileHost.getSpecs().get(1)); - assertEquals("spec3", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testAddTileAtInvalidPositionAddsToEnd() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec3"); - saveSetting("spec1,spec3"); - - mQSTileHost.addTile("spec2", 100); - mMainExecutor.runAllReady(); - - assertEquals(3, mQSTileHost.getSpecs().size()); - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec3", mQSTileHost.getSpecs().get(1)); - assertEquals("spec2", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testAddTileAtEnd() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles, "spec1,spec3"); - saveSetting("spec1,spec3"); - - mQSTileHost.addTile("spec2", QSTileHost.POSITION_AT_END); - mMainExecutor.runAllReady(); - - assertEquals(3, mQSTileHost.getSpecs().size()); - assertEquals("spec1", mQSTileHost.getSpecs().get(0)); - assertEquals("spec3", mQSTileHost.getSpecs().get(1)); - assertEquals("spec2", mQSTileHost.getSpecs().get(2)); - } - - @Test - public void testNoRepeatedSpecs_customTile() { - saveSetting(CUSTOM_TILE_SPEC); - - mQSTileHost.addTile(CUSTOM_TILE, /* end */ false); - mMainExecutor.runAllReady(); - - assertEquals(1, mQSTileHost.getSpecs().size()); - assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0)); - } - - @Test - public void testAddedAtBeginningOnDefault_customTile() { - saveSetting("spec1"); // seed - - mQSTileHost.addTile(CUSTOM_TILE); - mMainExecutor.runAllReady(); - - assertEquals(2, mQSTileHost.getSpecs().size()); - assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0)); - } - - @Test - public void testAddedAtBeginning_customTile() { - saveSetting("spec1"); // seed - - mQSTileHost.addTile(CUSTOM_TILE, /* end */ false); - mMainExecutor.runAllReady(); - - assertEquals(2, mQSTileHost.getSpecs().size()); - assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0)); - } - - @Test - public void testAddedAtEnd_customTile() { - saveSetting("spec1"); // seed - - mQSTileHost.addTile(CUSTOM_TILE, /* end */ true); - mMainExecutor.runAllReady(); - - assertEquals(2, mQSTileHost.getSpecs().size()); - assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(1)); - } - - @Test - public void testLoadTileSpec_repeated() { - List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2"); - - assertEquals(2, specs.size()); - assertEquals("spec1", specs.get(0)); - assertEquals("spec2", specs.get(1)); - } - - @Test - public void testLoadTileSpec_repeatedInDefault() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles_default, "spec1,spec1"); - List<String> specs = QSTileHost.loadTileSpecs(mContext, "default"); - } - - @Test - public void testLoadTileSpec_repeatedDefaultAndSetting() { - mContext.getOrCreateTestableResources() - .addOverride(R.string.quick_settings_tiles_default, "spec1"); - List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1"); - } - - @Test - public void testNotAvailableTile_specNotNull() { - saveSetting("na"); - verify(mQSLogger, never()).logTileDestroyed(isNull(), anyString()); - } - - @Test - public void testCustomTileRemoved_stateDeleted() { - mQSTileHost.changeTilesByUser(List.of(CUSTOM_TILE_SPEC), List.of()); - - verify(mCustomTileStatePersister) - .removeState(new TileServiceKey(CUSTOM_TILE, mQSTileHost.getUserId())); - } - - @Test - public void testRemoveTiles() { - saveSetting("spec1,spec2,spec3"); - - mQSTileHost.removeTiles(List.of("spec1", "spec2")); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec3"), mQSTileHost.getSpecs()); - } - - @Test - public void testTilesRemovedInQuickSuccession() { - saveSetting("spec1,spec2,spec3"); - mQSTileHost.removeTile("spec1"); - mQSTileHost.removeTile("spec3"); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec2"), mQSTileHost.getSpecs()); - assertEquals("spec2", getSetting()); - } - - @Test - public void testAddTileInMainThread() { - saveSetting("spec1,spec2"); - - mQSTileHost.addTile("spec3"); - assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs()); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs()); - } - - @Test - public void testRemoveTileInMainThread() { - saveSetting("spec1,spec2"); - - mQSTileHost.removeTile("spec1"); - assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs()); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec2"), mQSTileHost.getSpecs()); - } - - @Test - public void testRemoveTilesInMainThread() { - saveSetting("spec1,spec2,spec3"); - - mQSTileHost.removeTiles(List.of("spec3", "spec1")); - assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs()); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec2"), mQSTileHost.getSpecs()); - } - - @Test - public void testRemoveTileByUserInMainThread() { - saveSetting("spec1," + CUSTOM_TILE_SPEC); - - mQSTileHost.removeTileByUser(CUSTOM_TILE); - assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.getSpecs()); - - mMainExecutor.runAllReady(); - assertEquals(List.of("spec1"), mQSTileHost.getSpecs()); - } - - @Test - public void testNonValidTileNotStoredInSettings() { - saveSetting("spec1,not-valid"); - - assertEquals(List.of("spec1"), mQSTileHost.getSpecs()); - assertEquals("spec1", getSetting()); - } - - @Test - public void testNotAvailableTileNotStoredInSettings() { - saveSetting("spec1,na"); - - assertEquals(List.of("spec1"), mQSTileHost.getSpecs()); - assertEquals("spec1", getSetting()); - } - - @Test - public void testIsTileAdded_true() { - int user = mUserTracker.getUserId(); - getSharedPreferencesForUser(user) - .edit() - .putBoolean(CUSTOM_TILE.flattenToString(), true) - .apply(); - - assertTrue(mQSTileHost.isTileAdded(CUSTOM_TILE, user)); - } - - @Test - public void testIsTileAdded_false() { - int user = mUserTracker.getUserId(); - getSharedPreferencesForUser(user) - .edit() - .putBoolean(CUSTOM_TILE.flattenToString(), false) - .apply(); - - assertFalse(mQSTileHost.isTileAdded(CUSTOM_TILE, user)); - } - - @Test - public void testIsTileAdded_notSet() { - int user = mUserTracker.getUserId(); - - assertFalse(mQSTileHost.isTileAdded(CUSTOM_TILE, user)); - } - - @Test - public void testIsTileAdded_differentUser() { - int user = mUserTracker.getUserId(); - mUserFileManager.getSharedPreferences(QSTileHost.TILES, 0, user) - .edit() - .putBoolean(CUSTOM_TILE.flattenToString(), true) - .apply(); - - assertFalse(mQSTileHost.isTileAdded(CUSTOM_TILE, user + 1)); - } - - @Test - public void testSetTileAdded_true() { - int user = mUserTracker.getUserId(); - mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); - - assertTrue(getSharedPreferencesForUser(user) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testSetTileAdded_false() { - int user = mUserTracker.getUserId(); - mQSTileHost.setTileAdded(CUSTOM_TILE, user, false); - - assertFalse(getSharedPreferencesForUser(user) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testSetTileAdded_differentUser() { - int user = mUserTracker.getUserId(); - mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); - - assertFalse(getSharedPreferencesForUser(user + 1) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testSetTileRemoved_afterCustomTileChangedByUser() { - int user = mUserTracker.getUserId(); - saveSetting(CUSTOM_TILE_SPEC); - - // This will be done by TileServiceManager - mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); - - mQSTileHost.changeTilesByUser(mQSTileHost.getSpecs(), List.of("spec1")); - assertFalse(getSharedPreferencesForUser(user) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testSetTileRemoved_removedByUser() { - int user = mUserTracker.getUserId(); - saveSetting(CUSTOM_TILE_SPEC); - - // This will be done by TileServiceManager - mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); - - mQSTileHost.removeTileByUser(CUSTOM_TILE); - mMainExecutor.runAllReady(); - assertFalse(getSharedPreferencesForUser(user) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testSetTileRemoved_removedBySystem() { - int user = mUserTracker.getUserId(); - saveSetting("spec1," + CUSTOM_TILE_SPEC); - - // This will be done by TileServiceManager - mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); - - mQSTileHost.removeTile(CUSTOM_TILE_SPEC); - mMainExecutor.runAllReady(); - assertFalse(getSharedPreferencesForUser(user) - .getBoolean(CUSTOM_TILE.flattenToString(), false)); - } - - @Test - public void testProtoDump_noTiles() { - SystemUIProtoDump proto = new SystemUIProtoDump(); - mQSTileHost.dumpProto(proto, new String[0]); - - assertEquals(0, proto.tiles.length); - } - - @Test - public void testTilesInOrder() { - saveSetting("spec1," + CUSTOM_TILE_SPEC); - - SystemUIProtoDump proto = new SystemUIProtoDump(); - mQSTileHost.dumpProto(proto, new String[0]); - - assertEquals(2, proto.tiles.length); - assertEquals("spec1", proto.tiles[0].getSpec()); - assertEquals(CUSTOM_TILE.getPackageName(), proto.tiles[1].getComponentName().packageName); - assertEquals(CUSTOM_TILE.getClassName(), proto.tiles[1].getComponentName().className); - } - - private SharedPreferences getSharedPreferencesForUser(int user) { - return mUserFileManager.getSharedPreferences(QSTileHost.TILES, 0, user); - } - - private class TestQSTileHost extends QSTileHost { - TestQSTileHost(Context context, Lazy<NewQSTileFactory> newQSTileFactoryProvider, - QSFactory defaultFactory, Executor mainExecutor, - PluginManager pluginManager, TunerService tunerService, - Provider<AutoTileManager> autoTiles, - Lazy<ShadeController> shadeController, QSLogger qsLogger, - UserTracker userTracker, SecureSettings secureSettings, - CustomTileStatePersister customTileStatePersister, - TileLifecycleManager.Factory tileLifecycleManagerFactory, - UserFileManager userFileManager, QSPipelineFlagsRepository featureFlags) { - super(context, newQSTileFactoryProvider, defaultFactory, mainExecutor, pluginManager, - tunerService, autoTiles, shadeController, qsLogger, - userTracker, secureSettings, customTileStatePersister, - tileLifecycleManagerFactory, userFileManager, featureFlags); - } - - @Override - public void onPluginConnected(QSFactory plugin, Context pluginContext) { - } - - @Override - public void onPluginDisconnected(QSFactory plugin) { - } - } - - - private class TestTile extends QSTileImpl<QSTile.State> { - - protected TestTile(QSHost host) { - super( - host, - mock(QsEventLogger.class), - mock(Looper.class), - mock(Handler.class), - new FalsingManagerFake(), - mock(MetricsLogger.class), - mock(StatusBarStateController.class), - mock(ActivityStarter.class), - QSTileHostTest.this.mQSLogger - ); - } - - @Override - public State newTileState() { - State s = mock(QSTile.State.class); - when(s.toString()).thenReturn(MOCK_STATE_STRING); - return s; - } - - @Override - protected void handleClick(@Nullable Expandable expandable) {} - - @Override - protected void handleUpdateState(State state, Object arg) {} - - @Override - public int getMetricsCategory() { - return 0; - } - - @Override - public Intent getLongClickIntent() { - return null; - } - - @Override - public CharSequence getTileLabel() { - return null; - } - } - - private class TestTile1 extends TestTile { - - protected TestTile1(QSHost host) { - super(host); - } - } - - private class TestTile2 extends TestTile { - - protected TestTile2(QSHost host) { - super(host); - } - } - - private class TestTile3 extends TestTile { - - protected TestTile3(QSHost host) { - super(host); - } - } - - private class NotAvailableTile extends TestTile { - - protected NotAvailableTile(QSHost host) { - super(host); - } - - @Override - public boolean isAvailable() { - return false; - } - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt index 970cd17a731a..090a85b0d3f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt @@ -15,20 +15,6 @@ class QSPipelineFlagsRepositoryTest : SysuiTestCase() { private val underTest = QSPipelineFlagsRepository() @Test - fun pipelineFlagDisabled() { - mSetFlagsRule.disableFlags(Flags.FLAG_QS_NEW_PIPELINE) - - assertThat(underTest.pipelineEnabled).isFalse() - } - - @Test - fun pipelineFlagEnabled() { - mSetFlagsRule.enableFlags(Flags.FLAG_QS_NEW_PIPELINE) - - assertThat(underTest.pipelineEnabled).isTrue() - } - - @Test fun tilesFlagDisabled() { mSetFlagsRule.disableFlags(Flags.FLAG_QS_NEW_TILES) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java index ff8c4481adea..643debfbc810 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java @@ -6,20 +6,20 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; import android.os.Handler; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.testing.TestableLooper; +import android.testing.UiThreadTest; import android.view.View; +import android.view.Window; import android.widget.LinearLayout; import android.widget.Switch; import android.widget.TextView; @@ -44,20 +44,18 @@ import kotlinx.coroutines.CoroutineScope; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import java.util.List; -@Ignore("b/257089187") @SmallTest @RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) +@UiThreadTest public class InternetDialogDelegateTest extends SysuiTestCase { private static final String MOBILE_NETWORK_TITLE = "Mobile Title"; @@ -87,6 +85,8 @@ public class InternetDialogDelegateTest extends SysuiTestCase { private SystemUIDialog.Factory mSystemUIDialogFactory; @Mock private SystemUIDialog mSystemUIDialog; + @Mock + private Window mWindow; private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock()); private InternetDialogDelegate mInternetDialogDelegate; @@ -121,13 +121,16 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.getMobileNetworkSummary(anyInt())) .thenReturn(MOBILE_NETWORK_SUMMARY); when(mInternetDialogController.isWifiEnabled()).thenReturn(true); - + when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); mMockitoSession = ExtendedMockito.mockitoSession() .spyStatic(WifiEnterpriseRestrictionUtils.class) .startMocking(); when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true); when(mSystemUIDialogFactory.create(any(SystemUIDialog.Delegate.class))) .thenReturn(mSystemUIDialog); + when(mSystemUIDialog.getContext()).thenReturn(mContext); + when(mSystemUIDialog.getWindow()).thenReturn(mWindow); createInternetDialog(); } @@ -146,6 +149,8 @@ public class InternetDialogDelegateTest extends SysuiTestCase { mBgExecutor, mKeyguard, mSystemUIDialogFactory); + mInternetDialogDelegate.createDialog(); + mInternetDialogDelegate.onCreate(mSystemUIDialog, null); mInternetDialogDelegate.mAdapter = mInternetAdapter; mInternetDialogDelegate.mConnectedWifiEntry = mInternetWifiEntry; mInternetDialogDelegate.mWifiEntriesCount = mWifiEntries.size(); @@ -163,10 +168,12 @@ public class InternetDialogDelegateTest extends SysuiTestCase { mSeeAll = mDialogView.requireViewById(R.id.see_all_layout); mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); mAirplaneModeSummaryText = mDialogView.requireViewById(R.id.airplane_mode_summary); + mInternetDialogDelegate.onStart(mSystemUIDialog); } @After public void tearDown() { + mInternetDialogDelegate.onStop(mSystemUIDialog); mInternetDialogDelegate.dismissDialog(); mMockitoSession.finishMocking(); } @@ -191,59 +198,77 @@ public class InternetDialogDelegateTest extends SysuiTestCase { @Test public void updateDialog_withApmOn_internetDialogSubTitleGone() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test public void updateDialog_withApmOff_internetDialogSubTitleVisible() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test public void updateDialog_apmOffAndHasEthernet_showEthernet() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); when(mInternetDialogController.hasEthernet()).thenReturn(true); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test public void updateDialog_apmOffAndNoEthernet_hideEthernet() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); when(mInternetDialogController.hasEthernet()).thenReturn(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_apmOnAndHasEthernet_showEthernet() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); when(mInternetDialogController.hasEthernet()).thenReturn(true); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test public void updateDialog_apmOnAndNoEthernet_hideEthernet() { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); when(mInternetDialogController.hasEthernet()).thenReturn(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -252,41 +277,56 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); when(mInternetDialogController.hasActiveSubIdOnDds()).thenReturn(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + }); } @Test - public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayout() { - // Carrier network should be gone if airplane mode ON and Wi-Fi is off. + public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayoutVisible() { + // Carrier network should be visible if airplane mode ON and Wi-Fi is ON. when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); - when(mInternetDialogController.isWifiEnabled()).thenReturn(false); - + when(mInternetDialogController.isWifiEnabled()).thenReturn(true); mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); + }); + } - // Carrier network should be visible if airplane mode ON and Wi-Fi is ON. + @Test + public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayoutGone() { + // Carrier network should be gone if airplane mode ON and Wi-Fi is off. when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); - when(mInternetDialogController.isWifiEnabled()).thenReturn(true); - + when(mInternetDialogController.isWifiEnabled()).thenReturn(false); mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_apmOnAndNoCarrierNetwork_mobileDataLayoutGone() { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -295,11 +335,14 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); mInternetDialogDelegate.mConnectedWifiEntry = null; doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test @@ -308,30 +351,39 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); mInternetDialogDelegate.mConnectedWifiEntry = null; doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_apmOffAndHasCarrierNetwork_notShowApmSummary() { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_apmOnAndNoCarrierNetwork_notShowApmSummary() { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -340,10 +392,13 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isMobileDataEnabled()).thenReturn(true); mMobileToggleSwitch.setChecked(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileToggleSwitch.isChecked()).isTrue(); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileToggleSwitch.isChecked()).isTrue(); + }); } @Test @@ -352,26 +407,32 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isMobileDataEnabled()).thenReturn(false); mMobileToggleSwitch.setChecked(false); - mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mMobileToggleSwitch.isChecked()).isFalse(); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mMobileToggleSwitch.isChecked()).isFalse(); + }); } @Test public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() { - mInternetDialogDelegate.dismissDialog(); + when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn(1); doReturn(true).when(mInternetDialogController).hasActiveSubIdOnDds(); - createInternetDialog(); // The preconditions WiFi ON and Internet WiFi are already in setUp() doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); - LinearLayout secondaryLayout = mDialogView.requireViewById( - R.id.secondary_mobile_network_layout); - assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + LinearLayout secondaryLayout = mDialogView.requireViewById( + R.id.secondary_mobile_network_layout); + assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -379,10 +440,13 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The precondition WiFi ON is already in setUp() mInternetDialogDelegate.mConnectedWifiEntry = null; doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -390,14 +454,17 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The precondition WiFi ON is already in setUp() mInternetDialogDelegate.mConnectedWifiEntry = null; mInternetDialogDelegate.mWifiEntriesCount = 0; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - // Show a blank block to fix the dialog height even if there is no WiFi list - assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); - verify(mInternetAdapter).setMaxEntriesCount(3); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + // Show a blank block to fix the dialog height even if there is no WiFi list + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + verify(mInternetAdapter).setMaxEntriesCount(3); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + }); } @Test @@ -405,28 +472,34 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The precondition WiFi ON is already in setUp() mInternetDialogDelegate.mConnectedWifiEntry = null; mInternetDialogDelegate.mWifiEntriesCount = 1; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - // Show a blank block to fix the dialog height even if there is no WiFi list - assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); - verify(mInternetAdapter).setMaxEntriesCount(3); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + // Show a blank block to fix the dialog height even if there is no WiFi list + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + verify(mInternetAdapter).setMaxEntriesCount(3); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + }); } @Test public void updateDialog_wifiOnAndHasConnectedWifi_showAllWifiAndSeeAllArea() { // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialogDelegate.mWifiEntriesCount = 0; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); - // Show a blank block to fix the dialog height even if there is no WiFi list - assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); - verify(mInternetAdapter).setMaxEntriesCount(2); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + // Show a blank block to fix the dialog height even if there is no WiFi list + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + verify(mInternetAdapter).setMaxEntriesCount(2); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); + }); } @Test @@ -435,13 +508,16 @@ public class InternetDialogDelegateTest extends SysuiTestCase { mInternetDialogDelegate.mConnectedWifiEntry = null; mInternetDialogDelegate.mWifiEntriesCount = MAX_WIFI_ENTRY_COUNT; mInternetDialogDelegate.mHasMoreWifiEntries = true; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); - verify(mInternetAdapter).setMaxEntriesCount(3); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + verify(mInternetAdapter).setMaxEntriesCount(3); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test @@ -449,13 +525,16 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialogDelegate.mWifiEntriesCount = MAX_WIFI_ENTRY_COUNT - 1; mInternetDialogDelegate.mHasMoreWifiEntries = true; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); - verify(mInternetAdapter).setMaxEntriesCount(2); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + verify(mInternetAdapter).setMaxEntriesCount(2); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + }); } @Test @@ -463,32 +542,38 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The preconditions WiFi entries are already in setUp() when(mInternetDialogController.isDeviceLocked()).thenReturn(true); mInternetDialogDelegate.mConnectedWifiEntry = null; - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - // Show WiFi Toggle without background - assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiToggle.getBackground()).isNull(); - // Hide Wi-Fi networks and See all - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + // Show WiFi Toggle without background + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggle.getBackground()).isNull(); + // Hide Wi-Fi networks and See all + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_deviceLockedAndHasConnectedWifi_showWifiToggleWithBackground() { // The preconditions WiFi ON and WiFi entries are already in setUp() when(mInternetDialogController.isDeviceLocked()).thenReturn(true); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - // Show WiFi Toggle with highlight background - assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiToggle.getBackground()).isNotNull(); - // Hide Wi-Fi networks and See all - assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + // Show WiFi Toggle with highlight background + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggle.getBackground()).isNotNull(); + // Hide Wi-Fi networks and See all + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + }); } @Test @@ -496,13 +581,16 @@ public class InternetDialogDelegateTest extends SysuiTestCase { mInternetDialogDelegate.dismissDialog(); when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(false); createInternetDialog(); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - // Disable Wi-Fi switch and show restriction message in summary. - assertThat(mWifiToggleSwitch.isEnabled()).isFalse(); - assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + // Disable Wi-Fi switch and show restriction message in summary. + assertThat(mWifiToggleSwitch.isEnabled()).isFalse(); + assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0); + }); } @Test @@ -510,50 +598,38 @@ public class InternetDialogDelegateTest extends SysuiTestCase { mInternetDialogDelegate.dismissDialog(); when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true); createInternetDialog(); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - // Enable Wi-Fi switch and hide restriction message in summary. - assertThat(mWifiToggleSwitch.isEnabled()).isTrue(); - assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + // Enable Wi-Fi switch and hide restriction message in summary. + assertThat(mWifiToggleSwitch.isEnabled()).isTrue(); + assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE); + }); } @Test public void updateDialog_showSecondaryDataSub() { - mInternetDialogDelegate.dismissDialog(); + when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn(1); doReturn(1).when(mInternetDialogController).getActiveAutoSwitchNonDdsSubId(); doReturn(true).when(mInternetDialogController).hasActiveSubIdOnDds(); doReturn(false).when(mInternetDialogController).isAirplaneModeEnabled(); - createInternetDialog(); - clearInvocations(mInternetDialogController); mInternetDialogDelegate.updateDialog(true); + mBgExecutor.runAllReady(); - LinearLayout primaryLayout = mDialogView.requireViewById( - R.id.mobile_network_layout); - LinearLayout secondaryLayout = mDialogView.requireViewById( - R.id.secondary_mobile_network_layout); - - verify(mInternetDialogController).getMobileNetworkSummary(1); - assertThat(primaryLayout.getBackground()).isNotEqualTo(secondaryLayout.getBackground()); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + LinearLayout primaryLayout = mDialogView.requireViewById( + R.id.mobile_network_layout); + LinearLayout secondaryLayout = mDialogView.requireViewById( + R.id.secondary_mobile_network_layout); - // Tap the primary sub info - primaryLayout.performClick(); - ArgumentCaptor<AlertDialog> dialogArgumentCaptor = - ArgumentCaptor.forClass(AlertDialog.class); - verify(mDialogTransitionAnimator).showFromDialog(dialogArgumentCaptor.capture(), - eq(mSystemUIDialog), eq(null), eq(false)); - AlertDialog dialog = dialogArgumentCaptor.getValue(); - dialog.show(); - dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick(); - TestableLooper.get(this).processAllMessages(); - verify(mInternetDialogController).setAutoDataSwitchMobileDataPolicy(1, false); - - // Tap the secondary sub info - secondaryLayout.performClick(); - verify(mInternetDialogController).launchMobileNetworkSettings(any(View.class)); - - dialog.dismiss(); + verify(mInternetDialogController).getMobileNetworkSummary(1); + assertThat(primaryLayout.getBackground()).isNotEqualTo( + secondaryLayout.getBackground()); + }); } @Test @@ -561,6 +637,12 @@ public class InternetDialogDelegateTest extends SysuiTestCase { // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); + + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + }); assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); } @@ -569,8 +651,13 @@ public class InternetDialogDelegateTest extends SysuiTestCase { public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() { when(mInternetDialogController.isWifiEnabled()).thenReturn(false); when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); + + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + }); assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); } @@ -580,8 +667,13 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isWifiEnabled()).thenReturn(false); when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true); when(mInternetDialogController.isDeviceLocked()).thenReturn(true); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); + + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + }); assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); } @@ -591,33 +683,43 @@ public class InternetDialogDelegateTest extends SysuiTestCase { when(mInternetDialogController.isWifiEnabled()).thenReturn(false); when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true); when(mInternetDialogController.isDeviceLocked()).thenReturn(false); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE); - TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); - assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0); - assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull(); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE); + TextView wifiScanNotifyText = mDialogView.requireViewById( + R.id.wifi_scan_notify_text); + assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0); + assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull(); + }); } @Test public void updateDialog_wifiIsDisabled_uncheckWifiSwitch() { when(mInternetDialogController.isWifiEnabled()).thenReturn(false); mWifiToggleSwitch.setChecked(true); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mWifiToggleSwitch.isChecked()).isFalse(); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiToggleSwitch.isChecked()).isFalse(); + }); } @Test - public void updateDialog_wifiIsEnabled_checkWifiSwitch() { + public void updateDialog_wifiIsEnabled_checkWifiSwitch() throws Exception { when(mInternetDialogController.isWifiEnabled()).thenReturn(true); mWifiToggleSwitch.setChecked(false); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mWifiToggleSwitch.isChecked()).isTrue(); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mWifiToggleSwitch.isChecked()).isTrue(); + }); } @Test @@ -699,21 +801,28 @@ public class InternetDialogDelegateTest extends SysuiTestCase { public void updateDialog_shareWifiIntentNull_hideButton() { when(mInternetDialogController.getConfiguratorQrCodeGeneratorIntentOrNull(any())) .thenReturn(null); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()).isEqualTo(View.GONE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()).isEqualTo( + View.GONE); + }); } @Test public void updateDialog_shareWifiShareable_showButton() { when(mInternetDialogController.getConfiguratorQrCodeGeneratorIntentOrNull(any())) .thenReturn(new Intent()); - mInternetDialogDelegate.updateDialog(false); + mBgExecutor.runAllReady(); - assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()) - .isEqualTo(View.VISIBLE); + mInternetDialogDelegate.mDataInternetContent.observe( + mInternetDialogDelegate.mLifecycleOwner, i -> { + assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()) + .isEqualTo(View.VISIBLE); + }); } private void setNetworkVisible(boolean ethernetVisible, boolean mobileDataVisible, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java index 660e8da72bf1..39e4fc9831b6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java @@ -30,7 +30,7 @@ import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; +import static com.android.wm.shell.shared.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt index 3abdf6212f22..cb92b7745961 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt @@ -91,7 +91,12 @@ class NotificationTransitionAnimatorControllerTest : SysuiTestCase() { assertFalse(isExpandAnimationRunning!!) verify(headsUpManager) - .removeNotification(notificationKey, true /* releaseImmediately */, true /* animate */) + .removeNotification( + notificationKey, + /* releaseImmediately= */ true, + /* animate= */ true, + /* reason= */ "onIntentStarted(willAnimate=false)" + ) verify(onFinishAnimationCallback).run() } @@ -109,7 +114,12 @@ class NotificationTransitionAnimatorControllerTest : SysuiTestCase() { assertFalse(isExpandAnimationRunning!!) verify(headsUpManager) - .removeNotification(notificationKey, true /* releaseImmediately */, true /* animate */) + .removeNotification( + notificationKey, + /* releaseImmediately= */ true, + /* animate= */ true, + /* reason= */ "onLaunchAnimationCancelled()" + ) verify(onFinishAnimationCallback).run() } @@ -127,7 +137,12 @@ class NotificationTransitionAnimatorControllerTest : SysuiTestCase() { assertFalse(isExpandAnimationRunning!!) verify(headsUpManager) - .removeNotification(notificationKey, true /* releaseImmediately */, false /* animate */) + .removeNotification( + notificationKey, + /* releaseImmediately= */ true, + /* animate= */ false, + /* reason= */ "onLaunchAnimationEnd()" + ) verify(onFinishAnimationCallback).run() } @@ -161,12 +176,18 @@ class NotificationTransitionAnimatorControllerTest : SysuiTestCase() { controller.onTransitionAnimationEnd(isExpandingFullyAbove = true) verify(headsUpManager) - .removeNotification(summary.key, true /* releaseImmediately */, false /* animate */) + .removeNotification( + summary.key, + /* releaseImmediately= */ true, + /* animate= */ false, + /* reason= */ "onLaunchAnimationEnd()" + ) verify(headsUpManager, never()) .removeNotification( notification.entry.key, - true /* releaseImmediately */, - false /* animate */ + /* releaseImmediately= */ true, + /* animate= */ false, + /* reason= */ "onLaunchAnimationEnd()" ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index 8e9323fead92..b4f4138fd409 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -108,30 +108,31 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { private val executor = FakeExecutor(systemClock) private val huns: ArrayList<NotificationEntry> = ArrayList() private lateinit var helper: NotificationGroupTestHelper + @Before fun setUp() { MockitoAnnotations.initMocks(this) helper = NotificationGroupTestHelper(mContext) - coordinator = HeadsUpCoordinator( - logger, - systemClock, - headsUpManager, - headsUpViewBinder, - visualInterruptionDecisionProvider, - remoteInputManager, - launchFullScreenIntentProvider, - flags, - headerController, - executor) + coordinator = + HeadsUpCoordinator( + logger, + systemClock, + headsUpManager, + headsUpViewBinder, + visualInterruptionDecisionProvider, + remoteInputManager, + launchFullScreenIntentProvider, + flags, + headerController, + executor + ) coordinator.attach(notifPipeline) // capture arguments: collectionListener = withArgCaptor { verify(notifPipeline).addCollectionListener(capture()) } - notifPromoter = withArgCaptor { - verify(notifPipeline).addPromoter(capture()) - } + notifPromoter = withArgCaptor { verify(notifPipeline).addPromoter(capture()) } notifLifetimeExtender = withArgCaptor { verify(notifPipeline).addNotificationLifetimeExtender(capture()) } @@ -141,9 +142,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { beforeFinalizeFilterListener = withArgCaptor { verify(notifPipeline).addOnBeforeFinalizeFilterListener(capture()) } - onHeadsUpChangedListener = withArgCaptor { - verify(headsUpManager).addListener(capture()) - } + onHeadsUpChangedListener = withArgCaptor { verify(headsUpManager).addListener(capture()) } actionPressListener = withArgCaptor { verify(remoteInputManager).addActionPressListener(capture()) } @@ -187,8 +186,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0)) executor.advanceClockToLast() executor.runAllReady() - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false)) - verify(headsUpManager, times(1)).removeNotification(anyString(), eq(true)) + verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false), anyString()) + verify(headsUpManager, times(1)).removeNotification(anyString(), eq(true), anyString()) } @Test @@ -203,8 +202,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { executor.advanceClockToLast() executor.runAllReady() assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0)) - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false)) - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true)) + verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false), anyString()) + verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true), anyString()) } @Test @@ -217,7 +216,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { notifLifetimeExtender.cancelLifetimeExtension(entry) executor.advanceClockToLast() executor.runAllReady() - verify(headsUpManager, times(0)).removeNotification(anyString(), any()) + verify(headsUpManager, never()).removeNotification(anyString(), any(), anyString()) } @Test @@ -227,14 +226,14 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(false) whenever(headsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L) - assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason = */ 0)) + assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason= */ 0)) actionPressListener.accept(entry) executor.runAllReady() verify(endLifetimeExtension, times(1)).onEndLifetimeExtension(notifLifetimeExtender, entry) - collectionListener.onEntryRemoved(entry, /* reason = */ 0) - verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any()) + collectionListener.onEntryRemoved(entry, /* reason= */ 0) + verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any(), anyString()) } @Test @@ -248,8 +247,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(true) assertFalse(notifLifetimeExtender.maybeExtendLifetime(entry, 0)) - collectionListener.onEntryRemoved(entry, /* reason = */ 0) - verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any()) + collectionListener.onEntryRemoved(entry, /* reason= */ 0) + verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any(), anyString()) } @Test @@ -261,8 +260,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { addHUN(entry) executor.advanceClockToLast() executor.runAllReady() - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false)) - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true)) + verify(headsUpManager, never()).removeNotification(anyString(), eq(false), anyString()) + verify(headsUpManager, never()).removeNotification(anyString(), eq(true), anyString()) } @Test @@ -273,8 +272,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0)) executor.advanceClockToLast() executor.runAllReady() - verify(headsUpManager, times(1)).removeNotification(anyString(), eq(false)) - verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true)) + verify(headsUpManager, times(1)).removeNotification(anyString(), eq(false), anyString()) + verify(headsUpManager, never()).removeNotification(anyString(), eq(true), anyString()) } @Test @@ -326,9 +325,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { // THEN only promote the current HUN, mEntry assertTrue(notifPromoter.shouldPromoteToTopLevel(entry)) - assertFalse(notifPromoter.shouldPromoteToTopLevel(NotificationEntryBuilder() - .setPkg("test-package2") - .build())) + val testPackage2 = NotificationEntryBuilder().setPkg("test-package2").build() + assertFalse(notifPromoter.shouldPromoteToTopLevel(testPackage2)) } @Test @@ -338,9 +336,9 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { // THEN only section the current HUN, mEntry assertTrue(notifSectioner.isInSection(entry)) - assertFalse(notifSectioner.isInSection(NotificationEntryBuilder() - .setPkg("test-package") - .build())) + assertFalse( + notifSectioner.isInSection(NotificationEntryBuilder().setPkg("test-package").build()) + ) } @Test @@ -350,10 +348,12 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { // THEN only the current HUN, mEntry, should be lifetimeExtended assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* cancellationReason */ 0)) - assertFalse(notifLifetimeExtender.maybeExtendLifetime( - NotificationEntryBuilder() - .setPkg("test-package") - .build(), /* cancellationReason */ 0)) + assertFalse( + notifLifetimeExtender.maybeExtendLifetime( + NotificationEntryBuilder().setPkg("test-package").build(), + /* reason= */ 0 + ) + ) } @Test @@ -366,8 +366,9 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(entry)) verify(headsUpManager, never()).showNotification(entry) withArgCaptor<BindCallback> { - verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture()) - }.onBindFinished(entry) + verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture()) + } + .onBindFinished(entry) // THEN we tell the HeadsUpManager to show the notification verify(headsUpManager).showNotification(entry) @@ -430,7 +431,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { whenever(remoteInputManager.isSpinning(any())).thenReturn(false) // THEN heads up manager should remove the entry - verify(headsUpManager).removeNotification(entry.key, false) + verify(headsUpManager).removeNotification(eq(entry.key), eq(false), anyString()) } private fun addHUN(entry: NotificationEntry) { @@ -545,19 +546,22 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryAdded(groupSibling1) collectionListener.onEntryAdded(groupSibling2) - val beforeTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) - .build() + val beforeTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) - val afterTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupSibling2)) - .build() - beforeFinalizeFilterListener - .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup)) + val afterTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupSibling2)) + .build() + beforeFinalizeFilterListener.onBeforeFinalizeFilter( + listOf(groupPriority, afterTransformGroup) + ) verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any()) finishBind(groupPriority) @@ -583,19 +587,22 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryUpdated(groupSibling1) collectionListener.onEntryUpdated(groupSibling2) - val beforeTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) - .build() + val beforeTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) - val afterTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupSibling2)) - .build() - beforeFinalizeFilterListener - .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup)) + val afterTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupSibling2)) + .build() + beforeFinalizeFilterListener.onBeforeFinalizeFilter( + listOf(groupPriority, afterTransformGroup) + ) verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any()) finishBind(groupPriority) @@ -618,19 +625,22 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryUpdated(groupSummary) collectionListener.onEntryUpdated(groupPriority) - val beforeTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) - .build() + val beforeTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) - val afterTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupSibling2)) - .build() - beforeFinalizeFilterListener - .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup)) + val afterTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupSibling2)) + .build() + beforeFinalizeFilterListener.onBeforeFinalizeFilter( + listOf(groupPriority, afterTransformGroup) + ) verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any()) finishBind(groupPriority) @@ -654,19 +664,22 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryUpdated(groupSibling1) collectionListener.onEntryUpdated(groupSibling2) - val beforeTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) - .build() + val beforeTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupPriority, groupSibling2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) - val afterTransformGroup = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupSibling2)) - .build() - beforeFinalizeFilterListener - .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup)) + val afterTransformGroup = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupSibling2)) + .build() + beforeFinalizeFilterListener.onBeforeFinalizeFilter( + listOf(groupPriority, afterTransformGroup) + ) finishBind(groupSummary) verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupPriority), any()) @@ -688,10 +701,11 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryAdded(groupSummary) collectionListener.onEntryAdded(groupSibling1) collectionListener.onEntryAdded(groupSibling2) - val groupEntry = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupSibling1, groupSibling2)) - .build() + val groupEntry = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupSibling1, groupSibling2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry)) @@ -708,16 +722,16 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { @Test fun testNoTransferTwoChildAlert_withGroupAlertAll() { setShouldHeadsUp(groupSummary) - whenever(notifPipeline.allNotifs) - .thenReturn(listOf(groupSummary, groupChild1, groupChild2)) + whenever(notifPipeline.allNotifs).thenReturn(listOf(groupSummary, groupChild1, groupChild2)) collectionListener.onEntryAdded(groupSummary) collectionListener.onEntryAdded(groupChild1) collectionListener.onEntryAdded(groupChild2) - val groupEntry = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupChild1, groupChild2)) - .build() + val groupEntry = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupChild1, groupChild2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry)) @@ -742,10 +756,11 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { collectionListener.onEntryAdded(groupSummary) collectionListener.onEntryAdded(groupChild1) collectionListener.onEntryAdded(groupChild2) - val groupEntry = GroupEntryBuilder() - .setSummary(groupSummary) - .setChildren(listOf(groupChild1, groupChild2)) - .build() + val groupEntry = + GroupEntryBuilder() + .setSummary(groupSummary) + .setChildren(listOf(groupChild1, groupChild2)) + .build() beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry)) verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any()) beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry)) @@ -1045,9 +1060,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { .thenReturn(DecisionImpl.of(should)) } - private fun setDefaultShouldFullScreen( - originalDecision: FullScreenIntentDecision - ) { + private fun setDefaultShouldFullScreen(originalDecision: FullScreenIntentDecision) { val provider = visualInterruptionDecisionProvider whenever(provider.makeUnloggedFullScreenIntentDecision(any())).thenAnswer { val entry: NotificationEntry = it.getArgument(0) @@ -1059,11 +1072,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { entry: NotificationEntry, originalDecision: FullScreenIntentDecision ) { - whenever( - visualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry) - ).thenAnswer { - FullScreenIntentDecisionImpl(entry, originalDecision) - } + whenever(visualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry)) + .thenAnswer { FullScreenIntentDecisionImpl(entry, originalDecision) } } private fun verifyLoggedFullScreenIntentDecision( @@ -1089,7 +1099,8 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { private fun finishBind(entry: NotificationEntry) { verify(headsUpManager, never()).showNotification(entry) withArgCaptor<BindCallback> { - verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture()) - }.onBindFinished(entry) + verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture()) + } + .onBindFinished(entry) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java index 2d119174efff..95db95cd288b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.when; import android.animation.Animator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.os.Handler; +import android.platform.test.annotations.EnableFlags; import android.service.notification.StatusBarNotification; import android.testing.TestableLooper; import android.view.MotionEvent; @@ -52,6 +53,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; import org.junit.Before; import org.junit.Rule; @@ -672,17 +674,32 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { } @Test - public void testForceResetSwipeStateDoesNothingIfTranslationIsZero() { + @EnableFlags(NotificationContentAlphaOptimization.FLAG_NAME) + public void testForceResetSwipeStateDoesNothingIfTranslationIsZeroAndAlphaIsOne() { doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); doReturn(0f).when(mNotificationRow).getTranslationX(); + doReturn(1f).when(mNotificationRow).getAlpha(); mSwipeHelper.forceResetSwipeState(mNotificationRow); verify(mNotificationRow).getTranslationX(); + verify(mNotificationRow).getAlpha(); verifyNoMoreInteractions(mNotificationRow); } @Test + @EnableFlags(NotificationContentAlphaOptimization.FLAG_NAME) + public void testForceResetSwipeStateResetsAlphaIfTranslationIsZeroAndAlphaNotOne() { + doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); + doReturn(0f).when(mNotificationRow).getTranslationX(); + doReturn(0.5f).when(mNotificationRow).getAlpha(); + + mSwipeHelper.forceResetSwipeState(mNotificationRow); + + verify(mNotificationRow).setContentAlpha(eq(1f)); + } + + @Test public void testForceResetSwipeStateResetsTranslationAndAlpha() { doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); doReturn(10f).when(mNotificationRow).getTranslationX(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java deleted file mode 100644 index 665544d094e4..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui.statusbar.phone; - -import static com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE; -import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE; -import static com.android.systemui.statusbar.phone.AutoTileManager.DEVICE_CONTROLS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNotNull; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.display.ColorDisplayManager; -import android.hardware.display.NightDisplayListener; -import android.os.Handler; -import android.os.UserHandle; -import android.testing.TestableLooper; -import android.testing.TestableLooper.RunWithLooper; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.dagger.NightDisplayListenerModule; -import com.android.systemui.plugins.qs.QSTile; -import com.android.systemui.qs.AutoAddTracker; -import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.ReduceBrightColorsController; -import com.android.systemui.qs.UserSettingObserver; -import com.android.systemui.qs.external.CustomTile; -import com.android.systemui.res.R; -import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastDevice; -import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.DeviceControlsController; -import com.android.systemui.statusbar.policy.HotspotController; -import com.android.systemui.statusbar.policy.SafetyController; -import com.android.systemui.statusbar.policy.WalletController; -import com.android.systemui.util.settings.FakeSettings; -import com.android.systemui.util.settings.SecureSettings; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.mockito.stubbing.Answer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.inject.Named; - -@RunWith(AndroidJUnit4.class) -@RunWithLooper -@SmallTest -public class AutoTileManagerTest extends SysuiTestCase { - - private static final String TEST_SETTING = "setting"; - private static final String TEST_SPEC = "spec"; - private static final String TEST_SETTING_COMPONENT = "setting_component"; - private static final String TEST_COMPONENT = "test_pkg/test_cls"; - private static final String TEST_CUSTOM_SPEC = "custom(" + TEST_COMPONENT + ")"; - private static final String TEST_CUSTOM_SAFETY_CLASS = "safety_cls"; - private static final String TEST_CUSTOM_SAFETY_PKG = "safety_pkg"; - private static final String TEST_CUSTOM_SAFETY_SPEC = CustomTile.toSpec(new ComponentName( - TEST_CUSTOM_SAFETY_PKG, TEST_CUSTOM_SAFETY_CLASS)); - private static final String SEPARATOR = AutoTileManager.SETTING_SEPARATOR; - - private static final int USER = 0; - - @Mock private QSHost mQsHost; - @Mock private AutoAddTracker mAutoAddTracker; - @Mock private CastController mCastController; - @Mock private HotspotController mHotspotController; - @Mock private DataSaverController mDataSaverController; - @Mock private ManagedProfileController mManagedProfileController; - @Mock private NightDisplayListener mNightDisplayListener; - @Mock(answer = Answers.RETURNS_SELF) - private NightDisplayListenerModule.Builder mNightDisplayListenerBuilder; - @Mock private ReduceBrightColorsController mReduceBrightColorsController; - @Mock private DeviceControlsController mDeviceControlsController; - @Mock private WalletController mWalletController; - @Mock private SafetyController mSafetyController; - @Mock(answer = Answers.RETURNS_SELF) - private AutoAddTracker.Builder mAutoAddTrackerBuilder; - @Mock private Context mUserContext; - @Spy private PackageManager mPackageManager; - private final boolean mIsReduceBrightColorsAvailable = true; - - private AutoTileManager mAutoTileManager; // under test - - private SecureSettings mSecureSettings; - private ManagedProfileController.Callback mManagedProfileCallback; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mSecureSettings = new FakeSettings(); - - mSetFlagsRule.disableFlags(FLAG_QS_NEW_PIPELINE); - - mContext.getOrCreateTestableResources().addOverride( - R.array.config_quickSettingsAutoAdd, - new String[] { - TEST_SETTING + SEPARATOR + TEST_SPEC, - TEST_SETTING_COMPONENT + SEPARATOR + TEST_CUSTOM_SPEC - } - ); - mContext.getOrCreateTestableResources().addOverride( - com.android.internal.R.bool.config_nightDisplayAvailable, true); - mContext.getOrCreateTestableResources().addOverride( - R.string.safety_quick_settings_tile_class, TEST_CUSTOM_SAFETY_CLASS); - - when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker); - when(mQsHost.getUserContext()).thenReturn(mUserContext); - when(mUserContext.getUser()).thenReturn(UserHandle.of(USER)); - mPackageManager = Mockito.spy(mContext.getPackageManager()); - when(mPackageManager.getPermissionControllerPackageName()) - .thenReturn(TEST_CUSTOM_SAFETY_PKG); - Context context = Mockito.spy(mContext); - when(context.getPackageManager()).thenReturn(mPackageManager); - when(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener); - - mAutoTileManager = createAutoTileManager(context); - mAutoTileManager.init(); - } - - @After - public void tearDown() { - mAutoTileManager.destroy(); - } - - private AutoTileManager createAutoTileManager( - Context context, - AutoAddTracker.Builder autoAddTrackerBuilder, - HotspotController hotspotController, - DataSaverController dataSaverController, - ManagedProfileController managedProfileController, - NightDisplayListenerModule.Builder nightDisplayListenerBuilder, - CastController castController, - ReduceBrightColorsController reduceBrightColorsController, - DeviceControlsController deviceControlsController, - WalletController walletController, - SafetyController safetyController, - @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { - return new AutoTileManager(context, autoAddTrackerBuilder, mQsHost, - Handler.createAsync(TestableLooper.get(this).getLooper()), - mSecureSettings, - hotspotController, - dataSaverController, - managedProfileController, - mNightDisplayListenerBuilder, - castController, - reduceBrightColorsController, - deviceControlsController, - walletController, - safetyController, - isReduceBrightColorsAvailable); - } - - private AutoTileManager createAutoTileManager(Context context) { - return createAutoTileManager(context, mAutoAddTrackerBuilder, mHotspotController, - mDataSaverController, mManagedProfileController, mNightDisplayListenerBuilder, - mCastController, mReduceBrightColorsController, mDeviceControlsController, - mWalletController, mSafetyController, mIsReduceBrightColorsAvailable); - } - - @Test - public void testCreatedAutoTileManagerIsNotInitialized() { - AutoAddTracker.Builder builder = mock(AutoAddTracker.Builder.class, Answers.RETURNS_SELF); - AutoAddTracker tracker = mock(AutoAddTracker.class); - when(builder.build()).thenReturn(tracker); - HotspotController hC = mock(HotspotController.class); - DataSaverController dSC = mock(DataSaverController.class); - ManagedProfileController mPC = mock(ManagedProfileController.class); - NightDisplayListenerModule.Builder nDSB = mock(NightDisplayListenerModule.Builder.class); - CastController cC = mock(CastController.class); - ReduceBrightColorsController rBC = mock(ReduceBrightColorsController.class); - DeviceControlsController dCC = mock(DeviceControlsController.class); - WalletController wC = mock(WalletController.class); - SafetyController sC = mock(SafetyController.class); - - AutoTileManager manager = - createAutoTileManager(mock(Context.class), builder, hC, dSC, mPC, nDSB, cC, rBC, - dCC, wC, sC, true); - - verify(tracker, never()).initialize(); - verify(hC, never()).addCallback(any()); - verify(dSC, never()).addCallback(any()); - verify(mPC, never()).addCallback(any()); - verifyNoMoreInteractions(nDSB); - verify(cC, never()).addCallback(any()); - verify(rBC, never()).addCallback(any()); - verify(dCC, never()).setCallback(any()); - verify(wC, never()).getWalletPosition(); - verify(sC, never()).addCallback(any()); - assertNull(manager.getSecureSettingForKey(TEST_SETTING)); - assertNull(manager.getSecureSettingForKey(TEST_SETTING_COMPONENT)); - } - - @Test - public void testChangeUserWhenNotInitializedThrows() { - AutoTileManager manager = createAutoTileManager(mock(Context.class)); - - try { - manager.changeUser(UserHandle.of(USER + 1)); - fail(); - } catch (Exception e) { - // This should throw and take this path - } - } - - @Test - public void testChangeUserCallbacksStoppedAndStarted() throws Exception { - TestableLooper.get(this).runWithLooper(() -> - mAutoTileManager.changeUser(UserHandle.of(USER + 1)) - ); - - InOrder inOrderHotspot = inOrder(mHotspotController); - inOrderHotspot.verify(mHotspotController).removeCallback(any()); - inOrderHotspot.verify(mHotspotController).addCallback(any()); - - InOrder inOrderDataSaver = inOrder(mDataSaverController); - inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); - inOrderDataSaver.verify(mDataSaverController).addCallback(any()); - - InOrder inOrderManagedProfile = inOrder(mManagedProfileController); - inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); - inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); - - if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { - InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); - inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); - inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); - } - - InOrder inOrderReduceBrightColors = inOrder(mReduceBrightColorsController); - inOrderReduceBrightColors.verify(mReduceBrightColorsController).removeCallback(any()); - inOrderReduceBrightColors.verify(mReduceBrightColorsController).addCallback(any()); - - InOrder inOrderCast = inOrder(mCastController); - inOrderCast.verify(mCastController).removeCallback(any()); - inOrderCast.verify(mCastController).addCallback(any()); - - InOrder inOrderDevices = inOrder(mDeviceControlsController); - inOrderDevices.verify(mDeviceControlsController).removeCallback(); - inOrderDevices.verify(mDeviceControlsController).setCallback(any()); - - verify(mWalletController, times(2)).getWalletPosition(); - - InOrder inOrderSafety = inOrder(mSafetyController); - inOrderSafety.verify(mSafetyController).removeCallback(any()); - inOrderSafety.verify(mSafetyController).addCallback(any()); - - UserSettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); - assertEquals(USER + 1, setting.getCurrentUser()); - assertTrue(setting.isListening()); - } - - @Test - public void testChangeUserSomeCallbacksNotAdded() throws Exception { - when(mAutoAddTracker.isAdded("hotspot")).thenReturn(true); - when(mAutoAddTracker.isAdded("work")).thenReturn(true); - when(mAutoAddTracker.isAdded("cast")).thenReturn(true); - when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true); - - TestableLooper.get(this).runWithLooper(() -> - mAutoTileManager.changeUser(UserHandle.of(USER + 1)) - ); - - verify(mAutoAddTracker).changeUser(UserHandle.of(USER + 1)); - - InOrder inOrderHotspot = inOrder(mHotspotController); - inOrderHotspot.verify(mHotspotController).removeCallback(any()); - inOrderHotspot.verify(mHotspotController, never()).addCallback(any()); - - InOrder inOrderDataSaver = inOrder(mDataSaverController); - inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); - inOrderDataSaver.verify(mDataSaverController).addCallback(any()); - - InOrder inOrderManagedProfile = inOrder(mManagedProfileController); - inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); - inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); - - if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { - InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); - inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); - inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); - } - - InOrder inOrderReduceBrightColors = inOrder(mReduceBrightColorsController); - inOrderReduceBrightColors.verify(mReduceBrightColorsController).removeCallback(any()); - inOrderReduceBrightColors.verify(mReduceBrightColorsController).addCallback(any()); - - InOrder inOrderCast = inOrder(mCastController); - inOrderCast.verify(mCastController).removeCallback(any()); - inOrderCast.verify(mCastController, never()).addCallback(any()); - - InOrder inOrderDevices = inOrder(mDeviceControlsController); - inOrderDevices.verify(mDeviceControlsController).removeCallback(); - inOrderDevices.verify(mDeviceControlsController).setCallback(any()); - - verify(mWalletController, times(2)).getWalletPosition(); - - InOrder inOrderSafety = inOrder(mSafetyController); - inOrderSafety.verify(mSafetyController).removeCallback(any()); - inOrderSafety.verify(mSafetyController).addCallback(any()); - - UserSettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); - assertEquals(USER + 1, setting.getCurrentUser()); - assertFalse(setting.isListening()); - } - - @Test - public void testGetCurrentUserId() throws Exception { - assertEquals(USER, mAutoTileManager.getCurrentUserId()); - - TestableLooper.get(this).runWithLooper(() -> - mAutoTileManager.changeUser(UserHandle.of(USER + 100)) - ); - - assertEquals(USER + 100, mAutoTileManager.getCurrentUserId()); - } - - @Test - public void nightTileAdded_whenActivated() { - if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { - return; - } - mAutoTileManager.mNightDisplayCallback.onActivated(true); - verify(mQsHost).addTile("night"); - } - - @Test - public void nightTileNotAdded_whenDeactivated() { - if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { - return; - } - mAutoTileManager.mNightDisplayCallback.onActivated(false); - verify(mQsHost, never()).addTile("night"); - } - - @Test - public void nightTileAdded_whenNightModeTwilight() { - if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { - return; - } - mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( - ColorDisplayManager.AUTO_MODE_TWILIGHT); - verify(mQsHost).addTile("night"); - } - - @Test - public void nightTileAdded_whenNightModeCustom() { - if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { - return; - } - mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( - ColorDisplayManager.AUTO_MODE_CUSTOM_TIME); - verify(mQsHost).addTile("night"); - } - - @Test - public void nightTileNotAdded_whenNightModeDisabled() { - if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { - return; - } - mAutoTileManager.mNightDisplayCallback.onAutoModeChanged( - ColorDisplayManager.AUTO_MODE_DISABLED); - verify(mQsHost, never()).addTile("night"); - } - - @Test - public void reduceBrightColorsTileAdded_whenActivated() { - mAutoTileManager.mReduceBrightColorsCallback.onActivated(true); - verify(mQsHost).addTile("reduce_brightness"); - } - - @Test - public void reduceBrightColorsTileNotAdded_whenDeactivated() { - mAutoTileManager.mReduceBrightColorsCallback.onActivated(false); - verify(mQsHost, never()).addTile("reduce_brightness"); - } - - private static List<CastDevice> buildFakeCastDevice(boolean isCasting) { - CastDevice.CastState state = isCasting - ? CastDevice.CastState.Connected - : CastDevice.CastState.Disconnected; - return Collections.singletonList( - new CastDevice( - "id", - /* name= */ null, - /* description= */ null, - /* state= */ state, - /* origin= */ CastDevice.CastOrigin.MediaProjection, - /* tag= */ null)); - } - - @Test - public void castTileAdded_whenDeviceIsCasting() { - doReturn(buildFakeCastDevice(true)).when(mCastController).getCastDevices(); - mAutoTileManager.mCastCallback.onCastDevicesChanged(); - verify(mQsHost).addTile("cast"); - } - - @Test - public void castTileNotAdded_whenDeviceIsNotCasting() { - doReturn(buildFakeCastDevice(false)).when(mCastController).getCastDevices(); - mAutoTileManager.mCastCallback.onCastDevicesChanged(); - verify(mQsHost, never()).addTile("cast"); - } - - @Test - public void testSettingTileAdded_onChanged() { - changeValue(TEST_SETTING, 1); - verify(mAutoAddTracker).setTileAdded(TEST_SPEC); - verify(mQsHost).addTile(TEST_SPEC); - } - - @Test - public void testSettingTileAddedComponentAtEnd_onChanged() { - changeValue(TEST_SETTING_COMPONENT, 1); - verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC); - verify(mQsHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT) - , /* end */ true); - } - - @Test - public void testSettingTileAdded_onlyOnce() { - changeValue(TEST_SETTING, 1); - changeValue(TEST_SETTING, 2); - verify(mAutoAddTracker).setTileAdded(TEST_SPEC); - verify(mQsHost).addTile(TEST_SPEC); - } - - @Test - public void testSettingTileNotAdded_onChangedTo0() { - changeValue(TEST_SETTING, 0); - verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC); - verify(mQsHost, never()).addTile(TEST_SPEC); - } - - @Test - public void testSettingTileNotAdded_ifPreviouslyAdded() { - when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true); - - changeValue(TEST_SETTING, 1); - verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC); - verify(mQsHost, never()).addTile(TEST_SPEC); - } - - @Test - public void testSafetyTileNotAdded_ifPreviouslyAdded() { - ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); - mAutoTileManager.init(); - verify(mQsHost, times(1)).addTile(safetyComponent, true); - when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true); - mAutoTileManager.init(); - verify(mQsHost, times(1)).addTile(safetyComponent, true); - } - - @Test - public void testSafetyTileAdded_onUserChange() { - ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); - mAutoTileManager.init(); - verify(mQsHost, times(1)).addTile(safetyComponent, true); - when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(false); - mAutoTileManager.changeUser(UserHandle.of(USER + 1)); - verify(mQsHost, times(2)).addTile(safetyComponent, true); - } - - @Test - public void testSafetyTileRemoved_onSafetyCenterDisable() { - ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); - mAutoTileManager.init(); - when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true); - mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); - verify(mQsHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC); - } - - @Test - public void testSafetyTileAdded_onSafetyCenterEnable() { - ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); - mAutoTileManager.init(); - verify(mQsHost, times(1)).addTile(safetyComponent, true); - mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); - mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true); - verify(mQsHost, times(2)).addTile(safetyComponent, true); - } - - @Test - public void managedProfileAdded_tileAdded() { - when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(false); - when(mAutoAddTracker.getRestoredTilePosition(eq("work"))).thenReturn(2); - mAutoTileManager = createAutoTileManager(mContext); - Mockito.doAnswer((Answer<Object>) invocation -> { - mManagedProfileCallback = invocation.getArgument(0); - return null; - }).when(mManagedProfileController).addCallback(any()); - mAutoTileManager.init(); - when(mManagedProfileController.hasActiveProfile()).thenReturn(true); - - mManagedProfileCallback.onManagedProfileChanged(); - - verify(mQsHost, times(1)).addTile(eq("work"), eq(2)); - verify(mAutoAddTracker, times(1)).setTileAdded(eq("work")); - } - - @Test - public void managedProfileRemoved_tileRemoved() { - when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(true); - mAutoTileManager = createAutoTileManager(mContext); - Mockito.doAnswer((Answer<Object>) invocation -> { - mManagedProfileCallback = invocation.getArgument(0); - return null; - }).when(mManagedProfileController).addCallback(any()); - mAutoTileManager.init(); - when(mManagedProfileController.hasActiveProfile()).thenReturn(false); - - mManagedProfileCallback.onManagedProfileChanged(); - - verify(mQsHost, times(1)).removeTile(eq("work")); - verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work")); - } - - @Test - public void testAddControlsTileIfNotPresent() { - String spec = DEVICE_CONTROLS; - when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false); - when(mQsHost.getTiles()).thenReturn(new ArrayList<>()); - - mAutoTileManager.init(); - ArgumentCaptor<DeviceControlsController.Callback> captor = - ArgumentCaptor.forClass(DeviceControlsController.Callback.class); - - verify(mDeviceControlsController).setCallback(captor.capture()); - - captor.getValue().onControlsUpdate(3); - verify(mQsHost).addTile(spec, 3); - verify(mAutoAddTracker).setTileAdded(spec); - } - - @Test - public void testDontAddControlsTileIfPresent() { - String spec = DEVICE_CONTROLS; - when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false); - when(mQsHost.getTiles()).thenReturn(new ArrayList<>()); - - mAutoTileManager.init(); - ArgumentCaptor<DeviceControlsController.Callback> captor = - ArgumentCaptor.forClass(DeviceControlsController.Callback.class); - - verify(mDeviceControlsController).setCallback(captor.capture()); - - captor.getValue().removeControlsAutoTracker(); - verify(mQsHost, never()).addTile(spec, 3); - verify(mAutoAddTracker, never()).setTileAdded(spec); - verify(mAutoAddTracker).setTileRemoved(spec); - } - - @Test - public void testRemoveControlsTileFromTrackerWhenRequested() { - String spec = "controls"; - when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(true); - QSTile mockTile = mock(QSTile.class); - when(mockTile.getTileSpec()).thenReturn(spec); - when(mQsHost.getTiles()).thenReturn(List.of(mockTile)); - - mAutoTileManager.init(); - ArgumentCaptor<DeviceControlsController.Callback> captor = - ArgumentCaptor.forClass(DeviceControlsController.Callback.class); - - verify(mDeviceControlsController).setCallback(captor.capture()); - - captor.getValue().onControlsUpdate(3); - verify(mQsHost, never()).addTile(spec, 3); - verify(mAutoAddTracker, never()).setTileAdded(spec); - } - - - @Test - public void testEmptyArray_doesNotCrash() { - mContext.getOrCreateTestableResources().addOverride( - R.array.config_quickSettingsAutoAdd, new String[0]); - createAutoTileManager(mContext).destroy(); - } - - @Test - public void testMissingConfig_doesNotCrash() { - mContext.getOrCreateTestableResources().addOverride( - R.array.config_quickSettingsAutoAdd, null); - createAutoTileManager(mContext).destroy(); - } - - @Test - public void testUserChange_newNightDisplayListenerCreated() { - UserHandle newUser = UserHandle.of(1000); - mAutoTileManager.changeUser(newUser); - InOrder inOrder = inOrder(mNightDisplayListenerBuilder); - inOrder.verify(mNightDisplayListenerBuilder).setUser(newUser.getIdentifier()); - inOrder.verify(mNightDisplayListenerBuilder).build(); - } - - // Will only notify if it's listening - private void changeValue(String key, int value) { - mSecureSettings.putIntForUser(key, value, USER); - TestableLooper.get(this).processAllMessages(); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 5b4578153233..30e7247b325e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -33,8 +33,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.SysuiTestCase +import com.android.systemui.battery.BatteryMeterView import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.plugins.fakeDarkIconDispatcher import com.android.systemui.res.R import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.ShadeControllerImpl @@ -42,6 +45,7 @@ import com.android.systemui.shade.ShadeLogger import com.android.systemui.shade.ShadeViewController import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.statusbar.policy.Clock import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.window.StatusBarWindowStateController import com.android.systemui.unfold.SysUIUnfoldComponent @@ -70,7 +74,9 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class PhoneStatusBarViewControllerTest : SysuiTestCase() { + private val kosmos = Kosmos() + private val fakeDarkIconDispatcher = kosmos.fakeDarkIconDispatcher @Mock private lateinit var shadeViewController: ShadeViewController @Mock private lateinit var panelExpansionInteractor: PanelExpansionInteractor @Mock private lateinit var featureFlags: FeatureFlags @@ -91,6 +97,12 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { private lateinit var view: PhoneStatusBarView private lateinit var controller: PhoneStatusBarViewController + private val clockView: Clock + get() = view.requireViewById(R.id.clock) + + private val batteryView: BatteryMeterView + get() = view.requireViewById(R.id.battery) + private val unfoldConfig = UnfoldConfig() @Before @@ -114,16 +126,25 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test fun onViewAttachedAndDrawn_startListeningConfigurationControllerCallback() { val view = createViewMock() - val argumentCaptor = - ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java) + InstrumentationRegistry.getInstrumentation().runOnMainSync { controller = createAndInitController(view) } - verify(configurationController).addCallback(argumentCaptor.capture()) - argumentCaptor.value.onDensityOrFontScaleChanged() + verify(configurationController).addCallback(any()) + } + + @Test + fun onViewAttachedAndDrawn_darkReceiversRegistered() { + val view = createViewMock() + + InstrumentationRegistry.getInstrumentation().runOnMainSync { + controller = createAndInitController(view) + } - verify(view).onDensityOrFontScaleChanged() + assertThat(fakeDarkIconDispatcher.receivers.size).isEqualTo(2) + assertThat(fakeDarkIconDispatcher.receivers).contains(clockView) + assertThat(fakeDarkIconDispatcher.receivers).contains(batteryView) } @Test @@ -158,6 +179,21 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { } @Test + fun onViewDetached_darkReceiversUnregistered() { + val view = createViewMock() + + InstrumentationRegistry.getInstrumentation().runOnMainSync { + controller = createAndInitController(view) + } + + assertThat(fakeDarkIconDispatcher.receivers).isNotEmpty() + + controller.onViewDetached() + + assertThat(fakeDarkIconDispatcher.receivers).isEmpty() + } + + @Test fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false) val returnVal = @@ -353,7 +389,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { shadeLogger, viewUtil, configurationController, - mStatusOverlayHoverListenerFactory + mStatusOverlayHoverListenerFactory, + fakeDarkIconDispatcher, ) .create(view) .also { it.init() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt index abc50bc09e55..575b05123d38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt @@ -32,10 +32,10 @@ import android.view.View import android.view.WindowInsets import android.widget.FrameLayout import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT import com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP import com.android.systemui.Gefingerpoken import com.android.systemui.SysuiTestCase -import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.res.R import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.mockito.mock @@ -43,6 +43,7 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -64,7 +65,6 @@ class PhoneStatusBarViewTest : SysuiTestCase() { StatusBarContentInsetsProvider::class.java, contentInsetsProvider ) - mDependency.injectTestDependency(DarkIconDispatcher::class.java, mock<DarkIconDispatcher>()) mDependency.injectTestDependency(StatusBarWindowController::class.java, windowController) context.ensureTestableResources() view = spy(createStatusBarView()) @@ -185,21 +185,40 @@ class PhoneStatusBarViewTest : SysuiTestCase() { } @Test - fun onAttachedToWindow_updatesWindowHeight() { + @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onAttachedToWindow_flagOff_updatesWindowHeight() { view.onAttachedToWindow() verify(windowController).refreshStatusBarHeight() } @Test - fun onConfigurationChanged_updatesWindowHeight() { + @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onAttachedToWindow_flagOn_doesNotUpdateWindowHeight() { + view.onAttachedToWindow() + + verify(windowController, never()).refreshStatusBarHeight() + } + + @Test + @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onConfigurationChanged_flagOff_updatesWindowHeight() { view.onConfigurationChanged(Configuration()) verify(windowController).refreshStatusBarHeight() } @Test - fun onConfigurationChanged_multipleCalls_updatesWindowHeightMultipleTimes() { + @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onConfigurationChanged_flagOn_doesNotUpdateWindowHeight() { + view.onConfigurationChanged(Configuration()) + + verify(windowController, never()).refreshStatusBarHeight() + } + + @Test + @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onConfigurationChanged_multipleCalls_flagOff_updatesWindowHeightMultipleTimes() { view.onConfigurationChanged(Configuration()) view.onConfigurationChanged(Configuration()) view.onConfigurationChanged(Configuration()) @@ -209,6 +228,17 @@ class PhoneStatusBarViewTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT) + fun onConfigurationChanged_multipleCalls_flagOn_neverUpdatesWindowHeight() { + view.onConfigurationChanged(Configuration()) + view.onConfigurationChanged(Configuration()) + view.onConfigurationChanged(Configuration()) + view.onConfigurationChanged(Configuration()) + + verify(windowController, never()).refreshStatusBarHeight() + } + + @Test fun onAttachedToWindow_updatesLeftTopRightPaddingsBasedOnInsets() { val insets = Insets.of(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40) whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 9fa392f3a337..7a34e94ab362 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -434,7 +434,11 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { // Then verify(mBubblesManager).onUserChangedBubble(entry, false); - verify(mHeadsUpManager).removeNotification(entry.getKey(), true); + verify(mHeadsUpManager).removeNotification( + entry.getKey(), + /* releaseImmediately= */ true, + /* reason= */ "onNotificationBubbleIconClicked" + ); verifyNoMoreInteractions(mContentIntent); verifyNoMoreInteractions(mShadeController); @@ -456,7 +460,11 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { // Then verify(mBubblesManager).onUserChangedBubble(entry, true); - verify(mHeadsUpManager).removeNotification(entry.getKey(), true); + verify(mHeadsUpManager).removeNotification( + entry.getKey(), + /* releaseImmediately= */ true, + /* reason= */ "onNotificationBubbleIconClicked" + ); verify(mContentIntent, atLeastOnce()).isActivity(); verifyNoMoreInteractions(mContentIntent); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt index bf0a39be044b..06b3b57bd133 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt @@ -57,6 +57,7 @@ class ModesDialogDelegateTest : SysuiTestCase() { private val activityStarter = kosmos.activityStarter private val mockDialogTransitionAnimator = kosmos.mockDialogTransitionAnimator private val mockAnimationController = kosmos.mockActivityTransitionAnimatorController + private val mockDialogEventLogger = kosmos.mockModesDialogEventLogger private lateinit var underTest: ModesDialogDelegate @Before @@ -75,6 +76,7 @@ class ModesDialogDelegateTest : SysuiTestCase() { mockDialogTransitionAnimator, activityStarter, { kosmos.modesDialogViewModel }, + mockDialogEventLogger, kosmos.mainCoroutineContext, ) } @@ -121,4 +123,12 @@ class ModesDialogDelegateTest : SysuiTestCase() { assertThat(underTest.currentDialog).isNull() } + + @Test + fun openSettings_logsEvent() = + testScope.runTest { + val dialog: SystemUIDialog = mock() + underTest.openSettings(dialog) + verify(mockDialogEventLogger).logDialogSettings() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index 8b7d921a1c5b..4ea1a0ca9f2b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -229,6 +229,32 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { } @Test + public void testVolumeChangeW_inAudioSharing_doStateChanged() { + ArgumentCaptor<VolumeDialogController.State> stateCaptor = + ArgumentCaptor.forClass(VolumeDialogController.State.class); + mVolumeController.setDeviceInteractive(false); + when(mWakefullnessLifcycle.getWakefulness()) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE); + // For now, mAudioManager.getDevicesForStream returns DEVICE_NONE during audio sharing + when(mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC)) + .thenReturn(AudioManager.DEVICE_NONE); + + mVolumeController.mInAudioSharing = true; + mVolumeController.onVolumeChangedW(AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI); + verify(mCallback).onStateChanged(stateCaptor.capture()); + assertThat(stateCaptor.getValue().states.contains(AudioManager.STREAM_MUSIC)).isTrue(); + assertThat(stateCaptor.getValue().states.get(AudioManager.STREAM_MUSIC).routedToBluetooth) + .isTrue(); + + mVolumeController.mInAudioSharing = false; + mVolumeController.onVolumeChangedW(AudioManager.STREAM_MUSIC, AudioManager.FLAG_SHOW_UI); + verify(mCallback, times(2)).onStateChanged(stateCaptor.capture()); + assertThat(stateCaptor.getValue().states.contains(AudioManager.STREAM_MUSIC)).isTrue(); + assertThat(stateCaptor.getValue().states.get(AudioManager.STREAM_MUSIC).routedToBluetooth) + .isFalse(); + } + + @Test public void testOnRemoteVolumeChanged_newStream_noNullPointer() { MediaSession.Token token = new MediaSession.Token(Process.myUid(), null); mVolumeController.mMediaSessionsCallbacksW.onRemoteVolumeChanged(token, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java index 6fb70de3569d..60a15915fb77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java @@ -223,8 +223,11 @@ public class ImageWallpaperTest extends SysuiTestCase { } private void setBitmapDimensions(int bitmapWidth, int bitmapHeight) { + // TODO(b/281648899) remove the when(mWallpaperManager.peekBitmapDimensions(...)) when(mWallpaperManager.peekBitmapDimensions(anyInt(), anyBoolean())) .thenReturn(new Rect(0, 0, bitmapWidth, bitmapHeight)); + when(mWallpaperManager.peekBitmapDimensionsAsUser(anyInt(), anyBoolean(), anyInt())) + .thenReturn(new Rect(0, 0, bitmapWidth, bitmapHeight)); when(mWallpaperBitmap.getWidth()).thenReturn(bitmapWidth); when(mWallpaperBitmap.getHeight()).thenReturn(bitmapHeight); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt index 2021f02e5a8a..55aff130f691 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt @@ -123,11 +123,12 @@ class BubbleEducationControllerTest : SysUiStateTest() { /* taskId= */ 0, "locus", /* isDismissable= */ true, + directExecutor(), directExecutor() ) {} } else { val intent = Intent(Intent.ACTION_VIEW).setPackage(mContext.packageName) - Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor()) + Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor()) } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index e5e04dc9b82f..9dd3e53efa63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -459,7 +459,7 @@ public class BubblesTest extends SysuiTestCase { mContext.getSystemService(WindowManager.class)); mPositioner.setMaxBubbles(5); mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, mEducationController, - syncExecutor); + syncExecutor, syncExecutor); when(mUserManager.getProfiles(ActivityManager.getCurrentUser())).thenReturn( Collections.singletonList(mock(UserInfo.class))); @@ -2465,9 +2465,10 @@ public class BubblesTest extends SysuiTestCase { workEntry.setBubbleMetadata(getMetadata()); workEntry.setFlagBubble(true); + SyncExecutor executor = new SyncExecutor(); return new Bubble(mBubblesManager.notifToBubbleEntry(workEntry), null, - mock(Bubbles.PendingIntentCanceledListener.class), new SyncExecutor()); + mock(Bubbles.PendingIntentCanceledListener.class), executor, executor); } private BubbleEntry createBubbleEntry(boolean isConversation) { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt index e70631e89939..e8612d084b14 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelKosmos.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.bouncer.ui.viewmodel import android.content.applicationContext @@ -26,26 +28,31 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryBiometricsA import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.user.ui.viewmodel.userSwitcherViewModel import com.android.systemui.util.time.systemClock import kotlinx.coroutines.ExperimentalCoroutinesApi -@ExperimentalCoroutinesApi -val Kosmos.bouncerMessageViewModel by - Kosmos.Fixture { - BouncerMessageViewModel( - applicationContext = applicationContext, - applicationScope = testScope.backgroundScope, - bouncerInteractor = bouncerInteractor, - simBouncerInteractor = simBouncerInteractor, - authenticationInteractor = authenticationInteractor, - selectedUser = userSwitcherViewModel.selectedUser, - clock = systemClock, - biometricMessageInteractor = biometricMessageInteractor, - faceAuthInteractor = deviceEntryFaceAuthInteractor, - deviceUnlockedInteractor = deviceUnlockedInteractor, - deviceEntryBiometricsAllowedInteractor = deviceEntryBiometricsAllowedInteractor, - flags = composeBouncerFlags, - ) +val Kosmos.bouncerMessageViewModel by Fixture { + BouncerMessageViewModel( + applicationContext = applicationContext, + bouncerInteractor = bouncerInteractor, + simBouncerInteractor = simBouncerInteractor, + authenticationInteractor = authenticationInteractor, + userSwitcherViewModel = userSwitcherViewModel, + clock = systemClock, + biometricMessageInteractor = biometricMessageInteractor, + faceAuthInteractor = deviceEntryFaceAuthInteractor, + deviceUnlockedInteractor = deviceUnlockedInteractor, + deviceEntryBiometricsAllowedInteractor = deviceEntryBiometricsAllowedInteractor, + flags = composeBouncerFlags, + ) +} + +val Kosmos.bouncerMessageViewModelFactory by Fixture { + object : BouncerMessageViewModel.Factory { + override fun create(): BouncerMessageViewModel { + return bouncerMessageViewModel + } } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt index c3dad748064d..e405d17166b9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt @@ -21,6 +21,7 @@ package com.android.systemui.bouncer.ui.viewmodel import android.app.admin.devicePolicyManager import android.content.applicationContext import com.android.systemui.authentication.domain.interactor.authenticationInteractor +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor @@ -28,28 +29,97 @@ import com.android.systemui.bouncer.shared.flag.composeBouncerFlags import com.android.systemui.inputmethod.domain.interactor.inputMethodInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.kosmos.testDispatcher -import com.android.systemui.kosmos.testScope import com.android.systemui.user.domain.interactor.selectedUserInteractor import com.android.systemui.user.ui.viewmodel.userSwitcherViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.StateFlow -val Kosmos.bouncerViewModel by Fixture { - BouncerViewModel( +val Kosmos.bouncerSceneActionsViewModel by Fixture { + BouncerSceneActionsViewModel( + bouncerInteractor = bouncerInteractor, + ) +} + +val Kosmos.bouncerSceneActionsViewModelFactory by Fixture { + object : BouncerSceneActionsViewModel.Factory { + override fun create(): BouncerSceneActionsViewModel { + return bouncerSceneActionsViewModel + } + } +} + +val Kosmos.bouncerSceneContentViewModel by Fixture { + BouncerSceneContentViewModel( applicationContext = applicationContext, - applicationScope = testScope.backgroundScope, - mainDispatcher = testDispatcher, bouncerInteractor = bouncerInteractor, - inputMethodInteractor = inputMethodInteractor, - simBouncerInteractor = simBouncerInteractor, authenticationInteractor = authenticationInteractor, - selectedUserInteractor = selectedUserInteractor, devicePolicyManager = devicePolicyManager, - bouncerMessageViewModel = bouncerMessageViewModel, + bouncerMessageViewModelFactory = bouncerMessageViewModelFactory, flags = composeBouncerFlags, - selectedUser = userSwitcherViewModel.selectedUser, - users = userSwitcherViewModel.users, - userSwitcherMenu = userSwitcherViewModel.menu, - actionButton = bouncerActionButtonInteractor.actionButton, + userSwitcher = userSwitcherViewModel, + actionButtonInteractor = bouncerActionButtonInteractor, + pinViewModelFactory = pinBouncerViewModelFactory, + patternViewModelFactory = patternBouncerViewModelFactory, + passwordViewModelFactory = passwordBouncerViewModelFactory, ) } + +val Kosmos.bouncerSceneContentViewModelFactory by Fixture { + object : BouncerSceneContentViewModel.Factory { + override fun create(): BouncerSceneContentViewModel { + return bouncerSceneContentViewModel + } + } +} + +val Kosmos.pinBouncerViewModelFactory by Fixture { + object : PinBouncerViewModel.Factory { + override fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + authenticationMethod: AuthenticationMethodModel, + ): PinBouncerViewModel { + return PinBouncerViewModel( + applicationContext = applicationContext, + interactor = bouncerInteractor, + simBouncerInteractor = simBouncerInteractor, + isInputEnabled = isInputEnabled, + onIntentionalUserInput = onIntentionalUserInput, + authenticationMethod = authenticationMethod, + ) + } + } +} + +val Kosmos.patternBouncerViewModelFactory by Fixture { + object : PatternBouncerViewModel.Factory { + override fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + ): PatternBouncerViewModel { + return PatternBouncerViewModel( + applicationContext = applicationContext, + interactor = bouncerInteractor, + isInputEnabled = isInputEnabled, + onIntentionalUserInput = onIntentionalUserInput, + ) + } + } +} + +val Kosmos.passwordBouncerViewModelFactory by Fixture { + object : PasswordBouncerViewModel.Factory { + override fun create( + isInputEnabled: StateFlow<Boolean>, + onIntentionalUserInput: () -> Unit, + ): PasswordBouncerViewModel { + return PasswordBouncerViewModel( + interactor = bouncerInteractor, + inputMethodInteractor = inputMethodInteractor, + selectedUserInteractor = selectedUserInteractor, + isInputEnabled = isInputEnabled, + onIntentionalUserInput = onIntentionalUserInput, + ) + } + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/FakeUsageStatsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/FakeUsageStatsRepository.kt new file mode 100644 index 000000000000..d73de76986b9 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/FakeUsageStatsRepository.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data.repository + +import android.annotation.CurrentTimeMillisLong +import android.app.usage.UsageEvents +import android.os.UserHandle +import com.android.systemui.common.usagestats.data.model.UsageStatsQuery +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel +import com.android.systemui.common.usagestats.shared.model.ActivityEventModel.Lifecycle + +class FakeUsageStatsRepository : UsageStatsRepository { + private val events = mutableMapOf<UserHandle, MutableList<UsageEvents.Event>>() + + override suspend fun queryActivityEvents(query: UsageStatsQuery): List<ActivityEventModel> { + return events + .getOrDefault(query.user, emptyList()) + .filter { event -> + query.packageNames.isEmpty() || query.packageNames.contains(event.packageName) + } + .filter { event -> event.timeStamp in query.startTime until query.endTime } + .filter { event -> event.eventType.toActivityLifecycle() != Lifecycle.UNKNOWN } + .map { event -> + ActivityEventModel( + instanceId = event.instanceId, + packageName = event.packageName, + lifecycle = event.eventType.toActivityLifecycle(), + timestamp = event.timeStamp, + ) + } + } + + fun addEvent( + instanceId: Int, + user: UserHandle, + packageName: String, + @UsageEvents.Event.EventType type: Int, + @CurrentTimeMillisLong timestamp: Long, + ) { + events + .getOrPut(user) { mutableListOf() } + .add( + UsageEvents.Event(type, timestamp).apply { + mPackage = packageName + mInstanceId = instanceId + } + ) + } +} + +private fun Int.toActivityLifecycle(): Lifecycle = + when (this) { + UsageEvents.Event.ACTIVITY_RESUMED -> Lifecycle.RESUMED + UsageEvents.Event.ACTIVITY_PAUSED -> Lifecycle.PAUSED + UsageEvents.Event.ACTIVITY_STOPPED -> Lifecycle.STOPPED + UsageEvents.Event.ACTIVITY_DESTROYED -> Lifecycle.DESTROYED + else -> Lifecycle.UNKNOWN + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryKosmos.kt new file mode 100644 index 000000000000..7dac59e56fae --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/data/repository/UsageStatsRepositoryKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.data.repository + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.usageStatsRepository: UsageStatsRepository by Kosmos.Fixture { fakeUsageStatsRepository } +val Kosmos.fakeUsageStatsRepository by Kosmos.Fixture { FakeUsageStatsRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorKosmos.kt new file mode 100644 index 000000000000..06a680f9aba6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/usagestats/domain/interactor/UsageStatsInteractorKosmos.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.common.usagestats.domain.interactor + +import com.android.systemui.common.usagestats.data.repository.usageStatsRepository +import com.android.systemui.common.usagestats.domain.UsageStatsInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.settings.userTracker +import com.android.systemui.util.time.fakeSystemClock + +val Kosmos.usageStatsInteractor: UsageStatsInteractor by + Kosmos.Fixture { + UsageStatsInteractor( + userTracker = userTracker, + repository = usageStatsRepository, + systemClock = fakeSystemClock, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalMediaRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalMediaRepository.kt index 14b1984f2374..e0ed687416a9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalMediaRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalMediaRepository.kt @@ -28,7 +28,7 @@ class FakeCommunalMediaRepository : CommunalMediaRepository { fun mediaActive(timestamp: Long = 0L) { _mediaModel.value = CommunalMediaModel( - hasActiveMediaOrRecommendation = true, + hasAnyMediaOrRecommendation = true, createdTimestampMillis = timestamp, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt index ee48c105a987..2ab82214e497 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt @@ -17,6 +17,7 @@ package com.android.systemui.communal.domain.interactor import com.android.systemui.communal.data.repository.communalSceneRepository +import com.android.systemui.communal.shared.log.communalSceneLogger import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope @@ -24,6 +25,7 @@ val Kosmos.communalSceneInteractor: CommunalSceneInteractor by Kosmos.Fixture { CommunalSceneInteractor( applicationScope = applicationCoroutineScope, - communalSceneRepository = communalSceneRepository, + repository = communalSceneRepository, + logger = communalSceneLogger, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt new file mode 100644 index 000000000000..81242244b7a6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/WidgetTrampolineInteractorKosmos.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import com.android.systemui.common.usagestats.domain.interactor.usageStatsInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.logcatLogBuffer +import com.android.systemui.plugins.activityStarter +import com.android.systemui.shared.system.taskStackChangeListeners +import com.android.systemui.util.time.fakeSystemClock + +val Kosmos.widgetTrampolineInteractor: WidgetTrampolineInteractor by + Kosmos.Fixture { + WidgetTrampolineInteractor( + activityStarter = activityStarter, + systemClock = fakeSystemClock, + keyguardTransitionInteractor = keyguardTransitionInteractor, + taskStackChangeListeners = taskStackChangeListeners, + usageStatsInteractor = usageStatsInteractor, + logBuffer = logcatLogBuffer("WidgetTrampolineInteractor"), + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt new file mode 100644 index 000000000000..b560ee882929 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.shared.log + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.logcatLogBuffer + +val Kosmos.communalSceneLogger: CommunalSceneLogger by + Kosmos.Fixture { CommunalSceneLogger(logcatLogBuffer("CommunalSceneLogger")) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt index aa1968afba7d..cdfb297c27b9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt @@ -25,13 +25,13 @@ import kotlinx.coroutines.flow.asStateFlow class FakeContextualEducationRepository : ContextualEducationRepository { private val userGestureMap = mutableMapOf<Int, GestureEduModel>() - private val _gestureEduModels = MutableStateFlow(GestureEduModel()) + private val _gestureEduModels = MutableStateFlow(GestureEduModel(userId = 0)) private val gestureEduModelsFlow = _gestureEduModels.asStateFlow() private var currentUser: Int = 0 override fun setUser(userId: Int) { if (!userGestureMap.contains(userId)) { - userGestureMap[userId] = GestureEduModel() + userGestureMap[userId] = GestureEduModel(userId = userId) } // save data of current user to the map userGestureMap[currentUser] = _gestureEduModels.value diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index 4571c19d101a..54a6c0c1d182 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -60,13 +60,13 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository { override val bottomAreaAlpha: StateFlow<Float> = _bottomAreaAlpha private val _isKeyguardShowing = MutableStateFlow(false) - override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing + override val isKeyguardShowing: StateFlow<Boolean> = _isKeyguardShowing private val _isKeyguardUnlocked = MutableStateFlow(false) override val isKeyguardDismissible: StateFlow<Boolean> = _isKeyguardUnlocked.asStateFlow() private val _isKeyguardOccluded = MutableStateFlow(false) - override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded + override val isKeyguardOccluded: StateFlow<Boolean> = _isKeyguardOccluded private val _isDozing = MutableStateFlow(false) override val isDozing: StateFlow<Boolean> = _isDozing diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt index f1625948880f..64ae05131b5a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.domain.interactor +import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository @@ -38,6 +39,7 @@ var Kosmos.fromDreamingTransitionInteractor by mainDispatcher = testDispatcher, keyguardInteractor = keyguardInteractor, glanceableHubTransitions = glanceableHubTransitions, + communalSceneInteractor = communalSceneInteractor, communalSettingsInteractor = communalSettingsInteractor, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt index 450dcc25c903..d06bab2f5345 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt @@ -19,13 +19,11 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.util.mockito.mock import kotlinx.coroutines.ExperimentalCoroutinesApi @ExperimentalCoroutinesApi val Kosmos.dreamingToLockscreenTransitionViewModel by Fixture { DreamingToLockscreenTransitionViewModel( - fromDreamingTransitionInteractor = mock(), animationFlow = keyguardTransitionAnimationFlow, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt index e8b2dd232c1c..bcc73935de61 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt @@ -25,7 +25,7 @@ class FakeActivatable( var activationCount = 0 var cancellationCount = 0 - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { activationCount++ onActivation() try { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt index 9a56f2419669..c0bb9a6fbe14 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeSysUiViewModel.kt @@ -25,7 +25,7 @@ class FakeSysUiViewModel( var activationCount = 0 var cancellationCount = 0 - override suspend fun onActivated() { + override suspend fun onActivated(): Nothing { activationCount++ onActivation() try { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt new file mode 100644 index 000000000000..3d125e93a030 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/DarkIconDispatcherKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.plugins + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.fakeDarkIconDispatcher: FakeDarkIconDispatcher by + Kosmos.Fixture { FakeDarkIconDispatcher() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt new file mode 100644 index 000000000000..102a853a8250 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeDarkIconDispatcher.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.plugins + +import android.graphics.Rect +import java.util.ArrayList + +class FakeDarkIconDispatcher : DarkIconDispatcher { + val receivers = mutableListOf<DarkIconDispatcher.DarkReceiver>() + + override fun setIconsDarkArea(r: ArrayList<Rect>) {} + + override fun addDarkReceiver(receiver: DarkIconDispatcher.DarkReceiver) { + receivers.add(receiver) + } + + override fun removeDarkReceiver(receiver: DarkIconDispatcher.DarkReceiver) { + receivers.remove(receiver) + } + + override fun applyDark(`object`: DarkIconDispatcher.DarkReceiver) {} +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt index 9ff7dd590781..ffe6918a56f8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt @@ -27,6 +27,9 @@ class FakeFgsManagerController( numRunningPackages: Int = 0, ) : FgsManagerController { + var initialized = false + private set + override var numRunningPackages = numRunningPackages set(value) { if (value != field) { @@ -53,7 +56,9 @@ class FakeFgsManagerController( dialogDismissedListeners.forEach { it.onDialogDismissed() } } - override fun init() {} + override fun init() { + initialized = true + } override fun showDialog(expandable: Expandable?) {} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt new file mode 100644 index 000000000000..d37d8f39b9ee --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.composefragment.viewmodel + +import android.content.res.mainResources +import androidx.lifecycle.LifecycleCoroutineScope +import com.android.systemui.common.ui.domain.interactor.configurationInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.qs.footerActionsController +import com.android.systemui.qs.footerActionsViewModelFactory +import com.android.systemui.qs.ui.viewmodel.quickSettingsContainerViewModel +import com.android.systemui.shade.largeScreenHeaderHelper +import com.android.systemui.shade.transition.largeScreenShadeInterpolator +import com.android.systemui.statusbar.disableflags.data.repository.disableFlagsRepository +import com.android.systemui.statusbar.phone.keyguardBypassController +import com.android.systemui.statusbar.sysuiStatusBarStateController + +val Kosmos.qsFragmentComposeViewModelFactory by + Kosmos.Fixture { + object : QSFragmentComposeViewModel.Factory { + override fun create( + lifecycleScope: LifecycleCoroutineScope + ): QSFragmentComposeViewModel { + return QSFragmentComposeViewModel( + quickSettingsContainerViewModel, + mainResources, + footerActionsViewModelFactory, + footerActionsController, + sysuiStatusBarStateController, + keyguardBypassController, + disableFlagsRepository, + largeScreenShadeInterpolator, + configurationInteractor, + largeScreenHeaderHelper, + lifecycleScope, + ) + } + } + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt new file mode 100644 index 000000000000..67f611a040cf --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/system/TaskStackChangeListenersKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.system + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.taskStackChangeListeners: TaskStackChangeListeners by + Kosmos.Fixture { TaskStackChangeListeners.getTestInstance() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt index 0b309b59b0dc..4dd3ae762db7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt @@ -62,7 +62,9 @@ import com.android.systemui.statusbar.notification.people.PeopleNotificationIden import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.CoordinateOnClickListener import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpandableNotificationRowLogger import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener -import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED +import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger @@ -80,8 +82,6 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.wmshell.BubblesManager -import com.google.common.util.concurrent.MoreExecutors -import com.google.common.util.concurrent.SettableFuture import java.util.Optional import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -309,7 +309,7 @@ class ExpandableNotificationRowBuilder( entry.ranking = rb.build() } - return generateRow(entry, FLAG_CONTENT_VIEW_ALL) + return generateRow(entry, INFLATION_FLAGS) } private fun generateRow( @@ -374,7 +374,8 @@ class ExpandableNotificationRowBuilder( private const val PKG = "com.android.systemui" private const val UID = 1000 private val USER_HANDLE = UserHandle.of(ActivityManager.getCurrentUser()) - + private val INFLATION_FLAGS = + FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP private const val IS_CONVERSATION_FLAG = "test.isConversation" private val Notification.isConversationStyleNotification diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt index 1542bb349a97..3247525f1a36 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel +import com.android.systemui.dump.dumpManager import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -29,5 +30,6 @@ val Kosmos.notificationsPlaceholderViewModel by Fixture { shadeInteractor = shadeInteractor, headsUpNotificationInteractor = headsUpNotificationInteractor, featureFlags = featureFlagsClassic, + dumpManager = dumpManager, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt index 99bb47976c87..932e768676cb 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt @@ -33,6 +33,7 @@ var Kosmos.modesDialogDelegate: ModesDialogDelegate by dialogTransitionAnimator, activityStarter, { modesDialogViewModel }, + modesDialogEventLogger, mainCoroutineContext, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt new file mode 100644 index 000000000000..24e7a872d641 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy.ui.dialog + +import com.android.internal.logging.uiEventLogger +import com.android.systemui.kosmos.Kosmos +import org.mockito.kotlin.mock + +var Kosmos.modesDialogEventLogger by Kosmos.Fixture { ModesDialogEventLogger(uiEventLogger) } +var Kosmos.mockModesDialogEventLogger by Kosmos.Fixture { mock<ModesDialogEventLogger>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt new file mode 100644 index 000000000000..5146f77bbcf6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy.ui.dialog + +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.settingslib.notification.modes.TestModeBuilder +import com.android.systemui.SysuiTestCase +import com.android.systemui.qs.QSModesEvent +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper +class ModesDialogEventLoggerTest : SysuiTestCase() { + + private val uiEventLogger = UiEventLoggerFake() + private val underTest = ModesDialogEventLogger(uiEventLogger) + + @Test + fun testLogModeOn_manual() { + underTest.logModeOn(TestModeBuilder.MANUAL_DND_INACTIVE) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_ON, "android") + } + + @Test + fun testLogModeOff_manual() { + underTest.logModeOff(TestModeBuilder.MANUAL_DND_ACTIVE) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_OFF, "android") + } + + @Test + fun testLogModeSettings_manual() { + underTest.logModeSettings(TestModeBuilder.MANUAL_DND_ACTIVE) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_SETTINGS, "android") + } + + @Test + fun testLogModeOn_automatic() { + underTest.logModeOn(TestModeBuilder().setActive(true).setPackage("pkg1").build()) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_ON, "pkg1") + } + + @Test + fun testLogModeOff_automatic() { + underTest.logModeOff(TestModeBuilder().setActive(false).setPackage("pkg2").build()) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_OFF, "pkg2") + } + + @Test + fun testLogModeSettings_automatic() { + underTest.logModeSettings(TestModeBuilder().setPackage("pkg3").build()) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_SETTINGS, "pkg3") + } + + @Test + fun testLogOpenDurationDialog_manual() { + underTest.logOpenDurationDialog(TestModeBuilder.MANUAL_DND_INACTIVE) + + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + // package not logged for duration dialog as it only applies to manual mode + uiEventLogger[0].match(QSModesEvent.QS_MODES_DURATION_DIALOG, null) + } + + @Test + fun testLogOpenDurationDialog_automatic_doesNotLog() { + underTest.logOpenDurationDialog( + TestModeBuilder().setActive(false).setPackage("mypkg").build() + ) + + // ignore calls to open dialog on something other than the manual rule (shouldn't happen) + assertThat(uiEventLogger.numLogs()).isEqualTo(0) + } + + @Test + fun testLogDialogSettings() { + underTest.logDialogSettings() + assertThat(uiEventLogger.numLogs()).isEqualTo(1) + uiEventLogger[0].match(QSModesEvent.QS_MODES_SETTINGS, null) + } + + private fun UiEventLoggerFake.FakeUiEvent.match(event: QSModesEvent, modePackage: String?) { + assertThat(eventId).isEqualTo(event.id) + assertThat(packageName).isEqualTo(modePackage) + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt index 00020f8bb391..3571a737704b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt @@ -21,6 +21,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor import com.android.systemui.statusbar.policy.ui.dialog.modesDialogDelegate +import com.android.systemui.statusbar.policy.ui.dialog.modesDialogEventLogger import javax.inject.Provider val Kosmos.modesDialogViewModel: ModesDialogViewModel by @@ -30,5 +31,6 @@ val Kosmos.modesDialogViewModel: ModesDialogViewModel by zenModeInteractor, testDispatcher, Provider { modesDialogDelegate }.get(), + modesDialogEventLogger, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt new file mode 100644 index 000000000000..f502df0b4075 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.tutorial + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.model.sysUiState +import com.android.systemui.settings.displayTracker +import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor + +var Kosmos.touchpadGesturesInteractor: TouchpadGesturesInteractor by + Kosmos.Fixture { + TouchpadGesturesInteractor(sysUiState, displayTracker, testScope.backgroundScope) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt new file mode 100644 index 000000000000..577620347991 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.coroutines + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import org.junit.rules.TestWatcher +import org.junit.runner.Description + +/** + * Overrides main dispatcher to passed testDispatcher. You probably want to use it when using + * viewModelScope which has hardcoded main dispatcher. + */ +@OptIn(ExperimentalCoroutinesApi::class) +class MainDispatcherRule(val testDispatcher: TestDispatcher) : TestWatcher() { + override fun starting(description: Description) { + Dispatchers.setMain(testDispatcher) + } + + override fun finished(description: Description) { + Dispatchers.resetMain() + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt index 295e150e00d8..2e1ecfd3666e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt @@ -219,7 +219,7 @@ inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> = * * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException. */ -@Deprecated("Replace with mockito-kotlin", level = WARNING) +// TODO(359670968): rewrite this to use mockito-kotlin inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T = kotlinArgumentCaptor<T>().apply { block() }.value diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/OWNERS b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/OWNERS new file mode 100644 index 000000000000..1f07df9f1e8e --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/OWNERS @@ -0,0 +1 @@ +include /packages/SystemUI/src/com/android/systemui/volume/OWNERS
\ No newline at end of file diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt index 0a617d17b033..a4719e5a2492 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioSharingRepository.kt @@ -18,7 +18,6 @@ package com.android.systemui.volume.data.repository import com.android.settingslib.volume.data.repository.AudioSharingRepository import com.android.settingslib.volume.data.repository.GroupIdToVolumes -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -30,7 +29,7 @@ class FakeAudioSharingRepository : AudioSharingRepository { MutableStateFlow(TEST_GROUP_ID_INVALID) private val mutableVolumeMap: MutableStateFlow<GroupIdToVolumes> = MutableStateFlow(emptyMap()) - override val inAudioSharing: Flow<Boolean> = mutableInAudioSharing + override val inAudioSharing: StateFlow<Boolean> = mutableInAudioSharing override val primaryGroupId: StateFlow<Int> = mutablePrimaryGroupId override val secondaryGroupId: StateFlow<Int> = mutableSecondaryGroupId override val volumeMap: StateFlow<GroupIdToVolumes> = mutableVolumeMap diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt index e2d414e23abd..3ac565aeacf9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt @@ -22,7 +22,6 @@ import com.android.systemui.bluetooth.localBluetoothManager import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.volume.data.repository.audioRepository -import com.android.systemui.volume.data.repository.audioSharingRepository import com.android.systemui.volume.mediaOutputInteractor val Kosmos.audioOutputInteractor by @@ -37,6 +36,5 @@ val Kosmos.audioOutputInteractor by bluetoothAdapter, deviceIconInteractor, mediaOutputInteractor, - audioSharingRepository, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractorKosmos.kt index 9f11822adc0c..63a132565177 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputComponentInteractorKosmos.kt @@ -20,6 +20,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.domain.interactor.audioOutputInteractor +import com.android.systemui.volume.domain.interactor.audioSharingInteractor import com.android.systemui.volume.mediaDeviceSessionInteractor import com.android.systemui.volume.mediaOutputInteractor @@ -31,5 +32,6 @@ val Kosmos.mediaOutputComponentInteractor by audioOutputInteractor, audioModeInteractor, mediaOutputInteractor, + audioSharingInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt index a0a39d14dcf6..63386d016a7a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt @@ -17,15 +17,17 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.volume.data.repository.audioRepository +import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaOutputInteractor val Kosmos.audioSlidersInteractor by Kosmos.Fixture { AudioSlidersInteractor( - testScope.backgroundScope, + applicationCoroutineScope, mediaOutputInteractor, audioRepository, + audioModeInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt index 45a291e0e401..6e848ce26d9b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt @@ -18,6 +18,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope +import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaDeviceSessionInteractor import com.android.systemui.volume.mediaOutputInteractor import com.android.systemui.volume.panel.component.volume.domain.interactor.audioSlidersInteractor @@ -32,6 +33,7 @@ val Kosmos.audioVolumeComponentViewModel by mediaDeviceSessionInteractor, audioStreamSliderViewModelFactory, castVolumeSliderViewModelFactory, + audioModeInteractor, audioSlidersInteractor, ) } diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index 2c4bc7cb0d47..531fa4546bf9 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -78,8 +78,8 @@ import android.util.Range; import android.util.Size; import android.view.Surface; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +import android.annotation.NonNull; +import android.annotation.Nullable; import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl; import androidx.camera.extensions.impl.AutoPreviewExtenderImpl; import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl; diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt index cc9b70e387e8..639ebab4515b 100644 --- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt @@ -311,6 +311,7 @@ com.android.internal.util.ProcFileReader com.android.internal.util.QuickSelect com.android.internal.util.RingBuffer com.android.internal.util.SizedInputStream +com.android.internal.util.RateLimitingCache com.android.internal.util.StringPool com.android.internal.util.TokenBucket com.android.internal.util.XmlPullParserWrapper diff --git a/ravenwood/tools/ravenizer-fake/Android.bp b/ravenwood/tools/ravenizer-fake/Android.bp new file mode 100644 index 000000000000..7e2c407f2116 --- /dev/null +++ b/ravenwood/tools/ravenizer-fake/Android.bp @@ -0,0 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +sh_binary_host { + name: "ravenizer", + src: "ravenizer", + visibility: ["//visibility:public"], +} diff --git a/ravenwood/tools/ravenizer-fake/ravenizer b/ravenwood/tools/ravenizer-fake/ravenizer new file mode 100755 index 000000000000..84b3c8ee365e --- /dev/null +++ b/ravenwood/tools/ravenizer-fake/ravenizer @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright (C) 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# "Fake" ravenizer, which just copies the file. +# We need it to add ravenizer support to Soong on AOSP, +# when the actual ravenizer is not in AOSP yet. + +invalid_arg() { + echo "Ravenizer(fake): invalid args" 1>&2 + exit 1 +} + +(( $# >= 4 )) || invalid_arg +[[ "$1" == "--in-jar" ]] || invalid_arg +[[ "$3" == "--out-jar" ]] || invalid_arg + +echo "Ravenizer(fake): copiyng $2 to $4" + +cp "$2" "$4" diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java index b052d23971ab..aa57e0b84a63 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java @@ -16,8 +16,6 @@ package com.android.server.accessibility.magnification; -import static android.view.InputDevice.SOURCE_MOUSE; -import static android.view.InputDevice.SOURCE_STYLUS; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; @@ -307,12 +305,8 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } mDelegatingState = new DelegatingState(); - mDetectingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture() - ? new DetectingStateWithMultiFinger(context) - : new DetectingState(context); - mViewportDraggingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture() - ? new ViewportDraggingStateWithMultiFinger() - : new ViewportDraggingState(); + mDetectingState = new DetectingState(context); + mViewportDraggingState = new ViewportDraggingState(); mPanningScalingState = new PanningScalingState(context); mSinglePanningState = new SinglePanningState(context); mFullScreenMagnificationVibrationHelper = fullScreenMagnificationVibrationHelper; @@ -342,8 +336,12 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH cancelFling(); } handleTouchEventWith(mCurrentState, event, rawEvent, policyFlags); - } else if (Flags.enableMagnificationFollowsMouse() - && (event.getSource() == SOURCE_MOUSE || event.getSource() == SOURCE_STYLUS)) { + } + } + + @Override + void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (Flags.enableMagnificationFollowsMouse()) { if (mFullScreenMagnificationController.isActivated(mDisplayId)) { // TODO(b/354696546): Allow mouse/stylus to activate whichever display they are // over, rather than only interacting with the current display. @@ -351,8 +349,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH // Send through the mouse/stylus event handler. mMouseEventHandler.onEvent(event, mDisplayId); } - // Dispatch to normal event handling flow. - dispatchTransformedEvent(event, rawEvent, policyFlags); } } @@ -701,62 +697,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } } - final class ViewportDraggingStateWithMultiFinger extends ViewportDraggingState { - // LINT.IfChange(viewport_dragging_state_with_multi_finger) - @Override - public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) - throws GestureException { - final int action = event.getActionMasked(); - switch (action) { - case ACTION_POINTER_DOWN: { - clearAndTransitToPanningScalingState(); - } - break; - case ACTION_MOVE: { - if (event.getPointerCount() > 2) { - throw new GestureException("Should have one pointer down."); - } - final float eventX = event.getX(); - final float eventY = event.getY(); - if (mFullScreenMagnificationController.magnificationRegionContains( - mDisplayId, eventX, eventY)) { - mFullScreenMagnificationController.setCenter(mDisplayId, eventX, eventY, - /* animate */ mLastMoveOutsideMagnifiedRegion, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); - mLastMoveOutsideMagnifiedRegion = false; - } else { - mLastMoveOutsideMagnifiedRegion = true; - } - } - break; - - case ACTION_UP: - case ACTION_CANCEL: { - // If mScaleToRecoverAfterDraggingEnd >= 1.0, the dragging state is triggered - // by zoom in temporary, and the magnifier needs to recover to original scale - // after exiting dragging state. - // Otherwise, the magnifier should be disabled. - if (mScaleToRecoverAfterDraggingEnd >= 1.0f) { - zoomToScale(mScaleToRecoverAfterDraggingEnd, event.getX(), - event.getY()); - } else { - zoomOff(); - } - clear(); - mScaleToRecoverAfterDraggingEnd = Float.NaN; - transitionTo(mDetectingState); - } - break; - - case ACTION_DOWN: { - throw new GestureException( - "Unexpected event type: " + MotionEvent.actionToString(action)); - } - } - } - // LINT.ThenChange(:viewport_dragging_state) - } - /** * This class handles motion events when the event dispatcher has * determined that the user is performing a single-finger drag of the @@ -777,7 +717,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH protected boolean mLastMoveOutsideMagnifiedRegion; - // LINT.IfChange(viewport_dragging_state) @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) throws GestureException { @@ -788,7 +727,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } break; case ACTION_MOVE: { - if (event.getPointerCount() != 1) { + if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) { + if (event.getPointerCount() > 2) { + throw new GestureException("Should have at most two pointers down."); + } + } else if (event.getPointerCount() != 1) { throw new GestureException("Should have one pointer down."); } final float eventX = event.getX(); @@ -823,14 +766,20 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } break; - case ACTION_DOWN: case ACTION_POINTER_UP: { + if (!Flags.enableMagnificationMultipleFingerMultipleTapGesture()) { + throw new GestureException( + "Unexpected event type: " + MotionEvent.actionToString(action)); + } + } + break; + + case ACTION_DOWN: { throw new GestureException( "Unexpected event type: " + MotionEvent.actionToString(action)); } } } - // LINT.ThenChange(:viewport_dragging_state_with_multi_finger) private boolean isAlwaysOnMagnificationEnabled() { return mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled(); @@ -916,270 +865,31 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } } - final class DetectingStateWithMultiFinger extends DetectingState { - private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2; - // A flag set to true when two fingers have touched down. - // Used to indicate what next finger action should be. - private boolean mIsTwoFingerCountReached = false; - // A tap counts when two fingers are down and up once. - private int mCompletedTapCount = 0; - DetectingStateWithMultiFinger(Context context) { - super(context); - } - - // LINT.IfChange(detecting_state_with_multi_finger) - @Override - public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { - cacheDelayedMotionEvent(event, rawEvent, policyFlags); - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - mLastDetectingDownEventTime = event.getDownTime(); - mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - - mFirstPointerDownLocation.set(event.getX(), event.getY()); - - if (!mFullScreenMagnificationController.magnificationRegionContains( - mDisplayId, event.getX(), event.getY())) { - - transitionToDelegatingStateAndClear(); - - } else if (isMultiTapTriggered(2 /* taps */)) { - - // 3tap and hold - afterLongTapTimeoutTransitionToDraggingState(event); - - } else if (isTapOutOfDistanceSlop()) { - - transitionToDelegatingStateAndClear(); - - } else if (mDetectSingleFingerTripleTap - || mDetectTwoFingerTripleTap - // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay - // to ensure reachability of - // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN) - || isActivated()) { - - afterMultiTapTimeoutTransitionToDelegatingState(); - - } else { - - // Delegate pending events without delay - transitionToDelegatingStateAndClear(); - } - } - break; - case ACTION_POINTER_DOWN: { - mIsTwoFingerCountReached = mDetectTwoFingerTripleTap - && event.getPointerCount() == 2; - mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - - if (event.getPointerCount() == 2) { - if (isMultiFingerMultiTapTriggered( - TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) { - // 3tap and hold - afterLongTapTimeoutTransitionToDraggingState(event); - } else { - if (mDetectTwoFingerTripleTap) { - // If mDetectTwoFingerTripleTap, delay transition to the delegating - // state for mMultiTapMaxDelay to ensure reachability of - // multi finger multi tap - afterMultiTapTimeoutTransitionToDelegatingState(); - } - - if (isActivated()) { - // If activated, delay transition to the panning scaling - // state for tap timeout to ensure reachability of - // multi finger multi tap - storePointerDownLocation(mSecondPointerDownLocation, event); - mHandler.sendEmptyMessageDelayed( - MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, - ViewConfiguration.getTapTimeout()); - } - } - } else { - transitionToDelegatingStateAndClear(); - } - } - break; - case ACTION_POINTER_UP: { - // If it is a two-finger gesture, do not transition to the delegating state - // to ensure the reachability of - // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP) - if (!mIsTwoFingerCountReached) { - transitionToDelegatingStateAndClear(); - } - } - break; - case ACTION_MOVE: { - if (isFingerDown() - && distance(mLastDown, /* move */ event) > mSwipeMinDistance) { - // Swipe detected - transition immediately - - // For convenience, viewport dragging takes precedence - // over insta-delegating on 3tap&swipe - // (which is a rare combo to be used aside from magnification) - if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) { - transitionToViewportDraggingStateAndClear(event); - } else if (isMultiFingerMultiTapTriggered( - TWO_FINGER_GESTURE_MAX_TAPS - 1, event) - && event.getPointerCount() == 2) { - transitionToViewportDraggingStateAndClear(event); - } else if (isActivated() && event.getPointerCount() == 2) { - if (mOverscrollHandler != null - && overscrollState(event, mFirstPointerDownLocation) - == OVERSCROLL_VERTICAL_EDGE) { - transitionToDelegatingStateAndClear(); - } else { - //Primary pointer is swiping, so transit to PanningScalingState - transitToPanningScalingStateAndClear(); - } - } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled() - && isActivated() - && event.getPointerCount() == 1) { - if (mOverscrollHandler != null - && overscrollState(event, mFirstPointerDownLocation) - == OVERSCROLL_VERTICAL_EDGE) { - transitionToDelegatingStateAndClear(); - } else if (overscrollState(event, mFirstPointerDownLocation) - != OVERSCROLL_NONE) { - transitionToDelegatingStateAndClear(); - } else { - transitToSinglePanningStateAndClear(); - } - } else if (!mIsTwoFingerCountReached) { - // If it is a two-finger gesture, do not transition to the - // delegating state to ensure the reachability of - // the two-finger triple tap (triggerable with ACTION_UP) - transitionToDelegatingStateAndClear(); - } - } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation) - && distanceClosestPointerToPoint( - mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) { - // Second pointer is swiping, so transit to PanningScalingState - // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from - // multi finger multi tap - storePointerDownLocation(mSecondPointerDownLocation, event); - mHandler.sendEmptyMessageDelayed( - MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, - ViewConfiguration.getTapTimeout()); - } - } - break; - case ACTION_UP: { - - mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD); - mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE); - - if (!mFullScreenMagnificationController.magnificationRegionContains( - mDisplayId, event.getX(), event.getY())) { - transitionToDelegatingStateAndClear(); - - } else if (isMultiFingerMultiTapTriggered(TWO_FINGER_GESTURE_MAX_TAPS, event)) { - // Placing multiple fingers before a single finger, because achieving a - // multi finger multi tap also means achieving a single finger triple tap - onTripleTap(event); - - } else if (isMultiTapTriggered(3 /* taps */)) { - onTripleTap(/* up */ event); - - } else if ( - // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP - isFingerDown() - //TODO long tap should never happen here - && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay) - || (distance(mLastDown, mLastUp) >= mSwipeMinDistance)) - // If it is a two-finger but not reach 3 tap, do not transition to the - // delegating state to ensure the reachability of the triple tap - && mCompletedTapCount == 0) { - transitionToDelegatingStateAndClear(); - - } - } - break; - } - } - // LINT.ThenChange(:detecting_state) - - @Override - public void clear() { - mCompletedTapCount = 0; - setShortcutTriggered(false); - removePendingDelayedMessages(); - clearDelayedMotionEvents(); - mFirstPointerDownLocation.set(Float.NaN, Float.NaN); - mSecondPointerDownLocation.set(Float.NaN, Float.NaN); - } - - private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) { - if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) { - mCompletedTapCount++; - mIsTwoFingerCountReached = false; - } - - if (mDetectTwoFingerTripleTap && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) { - final boolean enabled = !isActivated(); - mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled); - } - return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount; - } - - void transitionToDelegatingStateAndClear() { - mCompletedTapCount = 0; - transitionTo(mDelegatingState); - sendDelayedMotionEvents(); - removePendingDelayedMessages(); - mFirstPointerDownLocation.set(Float.NaN, Float.NaN); - mSecondPointerDownLocation.set(Float.NaN, Float.NaN); - } - - void transitionToViewportDraggingStateAndClear(MotionEvent down) { - - if (DEBUG_DETECTING) Slog.i(mLogTag, "onTripleTapAndHold()"); - final boolean shortcutTriggered = mShortcutTriggered; - - // Only log the 3tap and hold event - if (!shortcutTriggered) { - final boolean enabled = !isActivated(); - if (mCompletedTapCount == TWO_FINGER_GESTURE_MAX_TAPS - 1) { - // Two finger triple tap and hold - mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled); - } else { - // Triple tap and hold also belongs to triple tap event - mMagnificationLogger.logMagnificationTripleTap(enabled); - } - } - clear(); - - mViewportDraggingState.prepareForZoomInTemporary(shortcutTriggered); - zoomInTemporary(down.getX(), down.getY(), shortcutTriggered); - transitionTo(mViewportDraggingState); - } - } - /** * This class handles motion events when the event dispatch has not yet * determined what the user is doing. It watches for various tap events. */ class DetectingState implements State, Handler.Callback { - protected static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1; - protected static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2; - protected static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3; + private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1; + private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2; + private static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3; final int mLongTapMinDelay; final int mSwipeMinDistance; final int mMultiTapMaxDelay; final int mMultiTapMaxDistance; + @Nullable final TwoFingerDoubleTapHandler mTwoFingerDoubleTapHandler; - protected MotionEventInfo mDelayedEventQueue; - protected MotionEvent mLastDown; - protected MotionEvent mPreLastDown; - protected MotionEvent mLastUp; - protected MotionEvent mPreLastUp; + private MotionEventInfo mDelayedEventQueue; + private MotionEvent mLastDown; + private MotionEvent mPreLastDown; + private MotionEvent mLastUp; + private MotionEvent mPreLastUp; - protected PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN); - protected PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN); - protected long mLastDetectingDownEventTime; + private PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN); + private PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN); + private long mLastDetectingDownEventTime; @VisibleForTesting boolean mShortcutTriggered; @@ -1191,6 +901,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH MagnificationGestureMatcher.getMagnificationMultiTapTimeout(context); mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop(); mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop(); + mTwoFingerDoubleTapHandler = + Flags.enableMagnificationMultipleFingerMultipleTapGesture() + ? new TwoFingerDoubleTapHandler() : null; } @Override @@ -1218,7 +931,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH return true; } - // LINT.IfChange(detecting_state) @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { cacheDelayedMotionEvent(event, rawEvent, policyFlags); @@ -1244,6 +956,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH transitionToDelegatingStateAndClear(); } else if (mDetectSingleFingerTripleTap + || (mTwoFingerDoubleTapHandler != null && mDetectTwoFingerTripleTap) // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay // to ensure reachability of // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN) @@ -1259,6 +972,12 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } break; case ACTION_POINTER_DOWN: { + if (mTwoFingerDoubleTapHandler != null) { + mTwoFingerDoubleTapHandler.onPointerDown(event); + break; + } + + // LINT.IfChange(action_pointer_down) if (isActivated() && event.getPointerCount() == 2) { storePointerDownLocation(mSecondPointerDownLocation, event); mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, @@ -1266,13 +985,26 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } else { transitionToDelegatingStateAndClear(); } + // LINT.ThenChange(:action_pointer_down_with_multi_finger) } break; case ACTION_POINTER_UP: { + if (mTwoFingerDoubleTapHandler != null) { + mTwoFingerDoubleTapHandler.onPointerUp(); + break; + } + // LINT.IfChange(action_pointer_up) transitionToDelegatingStateAndClear(); + // LINT.ThenChange(:action_pointer_up_with_multi_finger) } break; case ACTION_MOVE: { + if (mTwoFingerDoubleTapHandler != null) { + mTwoFingerDoubleTapHandler.onMove(event); + break; + } + + // LINT.IfChange(action_move) if (isFingerDown() && distance(mLastDown, /* move */ event) > mSwipeMinDistance) { // Swipe detected - transition immediately @@ -1313,12 +1045,20 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH //Second pointer is swiping, so transit to PanningScalingState transitToPanningScalingStateAndClear(); } + // LINT.ThenChange(:action_move_with_multi_finger) } break; case ACTION_UP: { mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD); + if (mTwoFingerDoubleTapHandler != null) { + mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE); + mTwoFingerDoubleTapHandler.onUp(event); + break; + } + + // LINT.IfChange(action_up) if (!mFullScreenMagnificationController.magnificationRegionContains( mDisplayId, event.getX(), event.getY())) { transitionToDelegatingStateAndClear(); @@ -1335,11 +1075,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH transitionToDelegatingStateAndClear(); } + // LINT.ThenChange(:action_up_with_multi_finger) } break; } } - // LINT.ThenChange(:detecting_state_with_multi_finger) protected void storePointerDownLocation(PointF pointerDownLocation, MotionEvent event) { final int index = event.getActionIndex(); @@ -1425,6 +1165,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH @Override public void clear() { + if (mTwoFingerDoubleTapHandler != null) { + mTwoFingerDoubleTapHandler.mCompletedTapCount = 0; + } setShortcutTriggered(false); removePendingDelayedMessages(); clearDelayedMotionEvents(); @@ -1501,9 +1244,13 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } void transitionToDelegatingStateAndClear() { + if (mTwoFingerDoubleTapHandler != null) { + mTwoFingerDoubleTapHandler.mCompletedTapCount = 0; + } transitionTo(mDelegatingState); sendDelayedMotionEvents(); removePendingDelayedMessages(); + mFirstPointerDownLocation.set(Float.NaN, Float.NaN); mSecondPointerDownLocation.set(Float.NaN, Float.NaN); } @@ -1543,9 +1290,15 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH // Only log the 3tap and hold event if (!shortcutTriggered) { - // Triple tap and hold also belongs to triple tap event final boolean enabled = !isActivated(); - mMagnificationLogger.logMagnificationTripleTap(enabled); + if (mTwoFingerDoubleTapHandler != null + && mTwoFingerDoubleTapHandler.shouldLogTwoFingerDoubleTap()) { + // Two finger double tap and hold + mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled); + } else { + // Triple tap and hold also belongs to triple tap event + mMagnificationLogger.logMagnificationTripleTap(enabled); + } } clear(); @@ -1604,6 +1357,173 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } return false; } + + final class TwoFingerDoubleTapHandler { + private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2; + // A tap counts when two fingers are down and up once. + private int mCompletedTapCount; + // A flag set to true when two fingers have touched down. + // Used to indicate what next finger action should be. + private boolean mIsTwoFingerCountReached; + + TwoFingerDoubleTapHandler() { + mCompletedTapCount = 0; + mIsTwoFingerCountReached = false; + } + + private void onPointerDown(MotionEvent event) { + mIsTwoFingerCountReached = mDetectTwoFingerTripleTap + && event.getPointerCount() == 2; + mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); + + // LINT.IfChange(action_pointer_down_with_multi_finger) + if (event.getPointerCount() == 2) { + if (isMultiFingerMultiTapTriggered( + TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) { + // 3tap and hold + afterLongTapTimeoutTransitionToDraggingState(event); + } else { + if (mDetectTwoFingerTripleTap) { + // If mDetectTwoFingerTripleTap, delay transition to the delegating + // state for mMultiTapMaxDelay to ensure reachability of + // multi finger multi tap + afterMultiTapTimeoutTransitionToDelegatingState(); + } + + if (isActivated()) { + // If activated, delay transition to the panning scaling + // state for tap timeout to ensure reachability of + // multi finger multi tap + storePointerDownLocation(mSecondPointerDownLocation, event); + mHandler.sendEmptyMessageDelayed( + MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, + ViewConfiguration.getTapTimeout()); + } + } + } else { + transitionToDelegatingStateAndClear(); + } + // LINT.ThenChange(:action_pointer_down) + } + + private void onMove(MotionEvent event) { + // LINT.IfChange(action_move_with_multi_finger) + if (isFingerDown() + && distance(mLastDown, /* move */ event) > mSwipeMinDistance) { + // Swipe detected - transition immediately + + // For convenience, viewport dragging takes precedence + // over insta-delegating on 3tap&swipe + // (which is a rare combo to be used aside from magnification) + if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) { + transitionToViewportDraggingStateAndClear(event); + } else if (isMultiFingerMultiTapTriggered( + TWO_FINGER_GESTURE_MAX_TAPS - 1, event) + && event.getPointerCount() == 2) { + transitionToViewportDraggingStateAndClear(event); + } else if (isActivated() && event.getPointerCount() == 2) { + if (mOverscrollHandler != null + && overscrollState(event, mFirstPointerDownLocation) + == OVERSCROLL_VERTICAL_EDGE) { + transitionToDelegatingStateAndClear(); + } else { + //Primary pointer is swiping, so transit to PanningScalingState + transitToPanningScalingStateAndClear(); + } + } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled() + && isActivated() + && event.getPointerCount() == 1) { + if (mOverscrollHandler != null + && overscrollState(event, mFirstPointerDownLocation) + == OVERSCROLL_VERTICAL_EDGE) { + transitionToDelegatingStateAndClear(); + } else if (overscrollState(event, mFirstPointerDownLocation) + != OVERSCROLL_NONE) { + transitionToDelegatingStateAndClear(); + } else { + transitToSinglePanningStateAndClear(); + } + } else if (!mIsTwoFingerCountReached) { + // If it is a two-finger gesture, do not transition to the + // delegating state to ensure the reachability of + // the two-finger triple tap (triggerable with ACTION_UP) + transitionToDelegatingStateAndClear(); + } + } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation) + && distanceClosestPointerToPoint( + mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) { + // Second pointer is swiping, so transit to PanningScalingState + // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from + // multi finger multi tap + storePointerDownLocation(mSecondPointerDownLocation, event); + mHandler.sendEmptyMessageDelayed( + MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, + ViewConfiguration.getTapTimeout()); + } + // LINT.ThenChange(:action_move) + } + + private void onPointerUp() { + // If it is a two-finger gesture, do not transition to the delegating state + // to ensure the reachability of + // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP) + // LINT.IfChange(action_pointer_up_with_multi_finger) + if (!mIsTwoFingerCountReached) { + transitionToDelegatingStateAndClear(); + } + // LINT.ThenChange(:action_pointer_up) + } + + private void onUp(MotionEvent event) { + // LINT.IfChange(action_up_with_multi_finger) + if (!mFullScreenMagnificationController.magnificationRegionContains( + mDisplayId, event.getX(), event.getY())) { + transitionToDelegatingStateAndClear(); + + } else if (isMultiFingerMultiTapTriggered( + TWO_FINGER_GESTURE_MAX_TAPS, event)) { + // Placing multiple fingers before a single finger, because achieving a + // multi finger multi tap also means achieving a single finger + // triple tap + onTripleTap(event); + + } else if (isMultiTapTriggered(3 /* taps */)) { + onTripleTap(/* up */ event); + + } else if ( + // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP + isFingerDown() + //TODO long tap should never happen here + && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay) + || (distance(mLastDown, mLastUp) >= mSwipeMinDistance)) + // If it is a two-finger but not reach 3 tap, do not + // transition to the delegating state to ensure the + // reachability of the triple tap + && mCompletedTapCount == 0) { + transitionToDelegatingStateAndClear(); + } + // LINT.ThenChange(:action_up) + } + + private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) { + if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) { + mCompletedTapCount++; + mIsTwoFingerCountReached = false; + } + + if (mDetectTwoFingerTripleTap + && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) { + final boolean enabled = !isActivated(); + mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled); + } + return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount; + } + + private boolean shouldLogTwoFingerDoubleTap() { + return mCompletedTapCount + == TwoFingerDoubleTapHandler.TWO_FINGER_GESTURE_MAX_TAPS - 1; + } + } } private void zoomInTemporary(float centerX, float centerY, boolean shortcutTriggered) { diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java index 08411c22b943..446123f07f64 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java @@ -127,49 +127,41 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo if (DEBUG_EVENT_STREAM) { storeEventInto(mDebugInputEventHistory, event); } - if (shouldDispatchTransformedEvent(event)) { - dispatchTransformedEvent(event, rawEvent, policyFlags); - } else { - onMotionEventInternal(event, rawEvent, policyFlags); - - final int action = event.getAction(); - if (action == MotionEvent.ACTION_DOWN) { - mCallback.onTouchInteractionStart(mDisplayId, getMode()); - } else if (action == ACTION_UP || action == ACTION_CANCEL) { - mCallback.onTouchInteractionEnd(mDisplayId, getMode()); + switch (event.getSource()) { + case SOURCE_TOUCHSCREEN: { + if (magnificationShortcutExists()) { + // Observe touchscreen events while magnification activation is detected. + onMotionEventInternal(event, rawEvent, policyFlags); + + final int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + mCallback.onTouchInteractionStart(mDisplayId, getMode()); + } else if (action == ACTION_UP || action == ACTION_CANCEL) { + mCallback.onTouchInteractionEnd(mDisplayId, getMode()); + } + // Return early: Do not dispatch event through normal eventing + // flow, it has been fully consumed by the magnifier. + return; + } + } break; + case SOURCE_MOUSE: + case SOURCE_STYLUS: { + if (magnificationShortcutExists() && Flags.enableMagnificationFollowsMouse()) { + handleMouseOrStylusEvent(event, rawEvent, policyFlags); + } } + break; + default: + break; } + // Dispatch event through normal eventing flow. + dispatchTransformedEvent(event, rawEvent, policyFlags); } - /** - * Some touchscreen, mouse and stylus events may modify magnifier state. Checks for whether the - * event should not be dispatched to the magnifier. - * - * @param event The event to check. - * @return `true` if the event should be sent through the normal event flow or `false` if it - * should be observed by magnifier. - */ - private boolean shouldDispatchTransformedEvent(MotionEvent event) { - if (event.getSource() == SOURCE_TOUCHSCREEN) { - if (mDetectSingleFingerTripleTap - || mDetectTwoFingerTripleTap - || mDetectShortcutTrigger) { - // Observe touchscreen events while magnification activation is detected. - return false; - } - } - if (Flags.enableMagnificationFollowsMouse()) { - if (event.isFromSource(SOURCE_MOUSE) || event.isFromSource(SOURCE_STYLUS)) { - // Note that mouse events include other mouse-like pointing devices - // such as touchpads and pointing sticks. - // Observe any mouse or stylus movement. - // We observe all movement to ensure that events continue to come in order, - // even though only some movement types actually move the viewport. - return false; - } - } - // Magnification dispatches (ignores) all other events - return true; + private boolean magnificationShortcutExists() { + return (mDetectSingleFingerTripleTap + || mDetectTwoFingerTripleTap + || mDetectShortcutTrigger); } final void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { @@ -202,6 +194,13 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo abstract void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags); /** + * Called when this MagnificationGestureHandler should handle a mouse or stylus motion event, + * but not re-dispatch it when completed. + */ + abstract void handleMouseOrStylusEvent( + MotionEvent event, MotionEvent rawEvent, int policyFlags); + + /** * Called when the shortcut target is magnification. */ public void notifyShortcutTriggered() { diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java index 1818cddbcf4c..a84140419166 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java @@ -147,9 +147,13 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl } @Override + void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + // Window Magnification viewport doesn't move with mouse events (yet). + } + + @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (event.getSource() != SOURCE_TOUCHSCREEN) { - // Window Magnification viewport doesn't move with mouse events (yet). return; } // To keep InputEventConsistencyVerifiers within GestureDetectors happy. diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java index 930af5e7f056..5044e93b293d 100644 --- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java @@ -71,6 +71,7 @@ import android.util.ArraySet; import android.util.Slog; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; +import android.view.autofill.AutofillValue; import com.android.internal.util.FrameworkStatsLog; @@ -244,10 +245,18 @@ public final class PresentationStatsEventLogger { Slog.e(TAG, "Failed to start new event because already have active event."); return; } + Slog.d(TAG, "Started new PresentationStatsEvent"); mEventInternal = Optional.of(new PresentationStatsEventInternal()); } /** + * Test use only, returns a copy of the events object + */ + Optional<PresentationStatsEventInternal> getInternalEvent() { + return mEventInternal; + } + + /** * Set request_id */ public void maybeSetRequestId(int requestId) { @@ -339,10 +348,16 @@ public final class PresentationStatsEventLogger { }); } - public void maybeSetCountShown(int datasets) { + /** + * This is called when a dataset is shown to the user. Will set the count shown, + * related timestamps and presentation reason. + */ + public void logWhenDatasetShown(int datasets) { mEventInternal.ifPresent( event -> { + maybeSetSuggestionPresentedTimestampMs(); event.mCountShown = datasets; + event.mNoPresentationReason = NOT_SHOWN_REASON_ANY_SHOWN; }); } @@ -405,7 +420,12 @@ public final class PresentationStatsEventLogger { public void maybeSetDisplayPresentationType(@UiType int uiType) { mEventInternal.ifPresent(event -> { - event.mDisplayPresentationType = getDisplayPresentationType(uiType); + // There are cases in which another UI type will show up after selects a dataset + // such as with Inline after Fill Dialog. Set as the first presentation type only. + if (event.mDisplayPresentationType + == AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE) { + event.mDisplayPresentationType = getDisplayPresentationType(uiType); + } }); } @@ -430,9 +450,12 @@ public final class PresentationStatsEventLogger { } public void maybeSetSuggestionSentTimestampMs(int timestamp) { - mEventInternal.ifPresent(event -> { - event.mSuggestionSentTimestampMs = timestamp; - }); + mEventInternal.ifPresent( + event -> { + if (event.mSuggestionSentTimestampMs == DEFAULT_VALUE_INT) { + event.mSuggestionSentTimestampMs = timestamp; + } + }); } public void maybeSetSuggestionSentTimestampMs() { @@ -481,8 +504,6 @@ public final class PresentationStatsEventLogger { public void maybeSetInlinePresentationAndSuggestionHostUid(Context context, int userId) { mEventInternal.ifPresent(event -> { - event.mDisplayPresentationType = - AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE; String imeString = Settings.Secure.getStringForUser(context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD, userId); if (TextUtils.isEmpty(imeString)) { @@ -602,40 +623,56 @@ public final class PresentationStatsEventLogger { } /** + * Sets the field length whenever the text changes. Will keep track of the first + * and last modification lengths. + */ + public void updateTextFieldLength(AutofillValue value) { + mEventInternal.ifPresent(event -> { + if (value == null || !value.isText()) { + return; + } + + int length = value.getTextValue().length(); + + if (event.mFieldFirstLength == DEFAULT_VALUE_INT) { + event.mFieldFirstLength = length; + } + event.mFieldLastLength = length; + }); + } + + /** * Set various timestamps whenever the ViewState is modified * * <p>If the ViewState contains ViewState.STATE_AUTOFILLED, sets field_autofilled_timestamp_ms * else, set field_first_modified_timestamp_ms (if unset) and field_last_modified_timestamp_ms */ - public void onFieldTextUpdated(ViewState state, int length) { + public void onFieldTextUpdated(ViewState state, AutofillValue value) { mEventInternal.ifPresent(event -> { - int timestamp = getElapsedTime(); - // Focused id should be set before this is called - if (state == null || state.id == null || state.id.getViewId() != event.mFocusedId) { - // if these don't match, the currently field different than before - Slog.w( - TAG, - "Bad view state for: " + event.mFocusedId); - return; - } + int timestamp = getElapsedTime(); + // Focused id should be set before this is called + if (state == null || state.id == null || state.id.getViewId() != event.mFocusedId) { + // if these don't match, the currently field different than before + Slog.w( + TAG, + "Bad view state for: " + event.mFocusedId + ", state: " + state); + return; + } - // Text changed because filling into form, just log Autofill timestamp - if ((state.getState() & ViewState.STATE_AUTOFILLED) != 0) { - event.mAutofilledTimestampMs = timestamp; - return; - } + updateTextFieldLength(value); - // Set length variables - if (event.mFieldFirstLength == DEFAULT_VALUE_INT) { - event.mFieldFirstLength = length; - } - event.mFieldLastLength = length; + // Text changed because filling into form, just log Autofill timestamp + if ((state.getState() & ViewState.STATE_AUTOFILLED) != 0) { + event.mAutofilledTimestampMs = timestamp; + return; + } - // Set timestamp variables - if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) { - event.mFieldModifiedFirstTimestampMs = timestamp; - } - event.mFieldModifiedLastTimestampMs = timestamp; + + // Set timestamp variables + if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) { + event.mFieldModifiedFirstTimestampMs = timestamp; + } + event.mFieldModifiedLastTimestampMs = timestamp; }); } @@ -796,7 +833,10 @@ public final class PresentationStatsEventLogger { }); } - public void logAndEndEvent() { + /** + * Finish and log the event. + */ + public void logAndEndEvent(String caller) { if (!mEventInternal.isPresent()) { Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same " + "event"); @@ -804,7 +844,8 @@ public final class PresentationStatsEventLogger { } PresentationStatsEventInternal event = mEventInternal.get(); if (sVerbose) { - Slog.v(TAG, "Log AutofillPresentationEventReported:" + Slog.v(TAG, "(" + caller + ") " + + "Log AutofillPresentationEventReported:" + " requestId=" + event.mRequestId + " sessionId=" + mSessionId + " mNoPresentationEventReason=" + event.mNoPresentationReason @@ -926,7 +967,7 @@ public final class PresentationStatsEventLogger { mEventInternal = Optional.empty(); } - private static final class PresentationStatsEventInternal { + static final class PresentationStatsEventInternal { int mRequestId; @NotShownReason int mNoPresentationReason = NOT_SHOWN_REASON_UNKNOWN; boolean mIsDatasetAvailable; diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 6dea8b052173..c75fd0b7e025 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -28,7 +28,6 @@ import static android.service.autofill.Dataset.PICK_REASON_PROVIDER_DETECTION_ON import static android.service.autofill.Dataset.PICK_REASON_PROVIDER_DETECTION_PREFERRED_WITH_PCC; import static android.service.autofill.Dataset.PICK_REASON_UNKNOWN; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_CREDMAN_BOTTOM_SHEET; -import static android.service.autofill.FillEventHistory.Event.UI_TYPE_DIALOG; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_UNKNOWN; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; @@ -67,10 +66,10 @@ import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATU import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_SUCCESS; import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_TIMEOUT; import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_TRANSACTION_TOO_LARGE; +import static com.android.server.autofill.Helper.SaveInfoStats; import static com.android.server.autofill.Helper.containsCharsInOrder; import static com.android.server.autofill.Helper.createSanitizers; import static com.android.server.autofill.Helper.getNumericValue; -import static com.android.server.autofill.Helper.SaveInfoStats; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import static com.android.server.autofill.Helper.toArray; @@ -78,6 +77,7 @@ import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTIC import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_RESULT_SUCCESS; import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_TYPE_DATASET_AUTHENTICATION; import static com.android.server.autofill.PresentationStatsEventLogger.AUTHENTICATION_TYPE_FULL_AUTHENTICATION; +import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_ANY_SHOWN; import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_NO_FOCUS; import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_FAILED; import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_TIMEOUT; @@ -1288,11 +1288,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Clears the existing response for the partition, reads a new structure, and then requests a * new fill response from the fill service. * - * <p> Also asks the IME to make an inline suggestions request if it's enabled. + * <p>Also asks the IME to make an inline suggestions request if it's enabled. */ @GuardedBy("mLock") - private void requestNewFillResponseLocked(@NonNull ViewState viewState, int newState, - int flags) { + private Optional<Integer> requestNewFillResponseLocked( + @NonNull ViewState viewState, int newState, int flags) { boolean isSecondary = shouldRequestSecondaryProvider(flags); final FillResponse existingResponse = isSecondary ? viewState.getSecondaryResponse() : viewState.getResponse(); @@ -1333,7 +1333,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mFillRequestEventLogger.maybeSetIsAugmented(true); mFillRequestEventLogger.logAndEndEvent(); triggerAugmentedAutofillLocked(flags); - return; + return Optional.empty(); } viewState.setState(newState); @@ -1353,11 +1353,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + ", flags=" + flags); } boolean isCredmanRequested = (flags & FLAG_VIEW_REQUESTS_CREDMAN_SERVICE) != 0; - mPresentationStatsEventLogger.maybeSetRequestId(requestId); - mPresentationStatsEventLogger.maybeSetIsCredentialRequest(isCredmanRequested); - mPresentationStatsEventLogger.maybeSetFieldClassificationRequestId( - mFieldClassificationIdSnapshot); - mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); mFillRequestEventLogger.maybeSetRequestId(requestId); mFillRequestEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); mSaveEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); @@ -1417,6 +1412,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Now request the assist structure data. requestAssistStructureLocked(requestId, flags); + + return Optional.of(requestId); } private boolean isRequestSupportFillDialog(int flags) { @@ -1662,6 +1659,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final LogMaker requestLog; synchronized (mLock) { + mPresentationStatsEventLogger.maybeSetRequestId(requestId); // Start a new FillResponse logger for the success case. mFillResponseEventLogger.startLogForNewResponse(); mFillResponseEventLogger.maybeSetRequestId(requestId); @@ -2419,7 +2417,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState NOT_SHOWN_REASON_REQUEST_FAILED); mFillResponseEventLogger.maybeSetResponseStatus(RESPONSE_STATUS_FAILURE); } - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("fill request failure"); mFillResponseEventLogger.maybeSetLatencyResponseProcessingMillis(); mFillResponseEventLogger.logAndEndEvent(); } @@ -2642,6 +2640,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void onShown(int uiType, int numDatasetsShown) { synchronized (mLock) { mPresentationStatsEventLogger.maybeSetDisplayPresentationType(uiType); + mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( + NOT_SHOWN_REASON_ANY_SHOWN); if (uiType == UI_TYPE_INLINE) { // Inline Suggestions are inflated one at a time @@ -2657,7 +2657,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mLoggedInlineDatasetShown = true; } else { - mPresentationStatsEventLogger.maybeSetCountShown(numDatasetsShown); + mPresentationStatsEventLogger.logWhenDatasetShown(numDatasetsShown); // Explicitly sets maybeSetSuggestionPresentedTimestampMs mPresentationStatsEventLogger.maybeSetSuggestionPresentedTimestampMs(); mService.logDatasetShown(this.id, mClientState, uiType); @@ -2800,7 +2800,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (mCurrentViewId == null) { return; } + mPresentationStatsEventLogger.logAndEndEvent("fallback from fill dialog"); + startNewEventForPresentationStatsEventLogger(); final ViewState currentView = mViewStates.get(mCurrentViewId); + logPresentationStatsOnViewEnteredLocked(currentView.getResponse(), false); currentView.maybeCallOnFillReady(mFlags); } } @@ -2850,7 +2853,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (requestId == AUGMENTED_AUTOFILL_REQUEST_ID) { setAuthenticationResultForAugmentedAutofillLocked(data, authenticationId); // Augmented autofill is not logged. - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("authentication - augmented"); return; } if (mResponses == null) { @@ -2859,7 +2862,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "setAuthenticationResultLocked(" + authenticationId + "): no responses"); mPresentationStatsEventLogger.maybeSetAuthenticationResult( AUTHENTICATION_RESULT_FAILURE); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("authentication - no response"); removeFromService(); return; } @@ -2870,7 +2873,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "no authenticated response"); mPresentationStatsEventLogger.maybeSetAuthenticationResult( AUTHENTICATION_RESULT_FAILURE); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("authentication - bad response"); removeFromService(); return; } @@ -2885,7 +2888,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "no dataset with index " + datasetIdx + " on fill response"); mPresentationStatsEventLogger.maybeSetAuthenticationResult( AUTHENTICATION_RESULT_FAILURE); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("authentication - no datasets"); removeFromService(); return; } @@ -3330,7 +3333,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( PresentationStatsEventLogger.getNoPresentationEventReason(commitReason)); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("Context committed"); final int flags = lastResponse.getFlags(); if ((flags & FillResponse.FLAG_TRACK_CONTEXT_COMMITED) == 0) { @@ -4299,6 +4302,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Starts (if necessary) a new fill request upon entering a view. * * <p>A new request will be started in 2 scenarios: + * * <ol> * <li>If the user manually requested autofill. * <li>If the view is part of a new partition. @@ -4307,18 +4311,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * @param id The id of the view that is entered. * @param viewState The view that is entered. * @param flags The flag that was passed by the AutofillManager. - * * @return {@code true} if a new fill response is requested. */ @GuardedBy("mLock") - private boolean requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id, - @NonNull ViewState viewState, int flags) { + private Optional<Integer> requestNewFillResponseOnViewEnteredIfNecessaryLocked( + @NonNull AutofillId id, @NonNull ViewState viewState, int flags) { // Force new response for manual request if ((flags & FLAG_MANUAL_REQUEST) != 0) { mSessionFlags.mAugmentedAutofillOnly = false; if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags); - requestNewFillResponseLocked(viewState, ViewState.STATE_RESTARTED_SESSION, flags); - return true; + return requestNewFillResponseLocked( + viewState, ViewState.STATE_RESTARTED_SESSION, flags); } // If it's not, then check if it should start a partition. @@ -4331,15 +4334,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Sometimes activity contain IMPORTANT_FOR_AUTOFILL_NO fields which marks session as // augmentedOnly, but other fields are still fillable by standard autofill. mSessionFlags.mAugmentedAutofillOnly = false; - requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_PARTITION, flags); - return true; + return requestNewFillResponseLocked( + viewState, ViewState.STATE_STARTED_PARTITION, flags); } if (sVerbose) { Slog.v(TAG, "Not starting new partition for view " + id + ": " + viewState.getStateAsString()); } - return false; + return Optional.empty(); } /** @@ -4428,31 +4431,32 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int action, int flags) { if (mDestroyed) { - Slog.w(TAG, "Call to Session#updateLocked() rejected - session: " - + id + " destroyed"); + Slog.w(TAG, "updateLocked(" + id + "): rejected - session: destroyed"); return; } if (action == ACTION_RESPONSE_EXPIRED) { mSessionFlags.mExpiredResponse = true; if (sDebug) { - Slog.d(TAG, "Set the response has expired."); + Slog.d(TAG, "updateLocked(" + id + "): Set the response has expired."); } mPresentationStatsEventLogger.maybeSetNoPresentationEventReasonIfNoReasonExists( NOT_SHOWN_REASON_VIEW_CHANGED); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("ACTION_RESPONSE_EXPIRED"); return; } id.setSessionId(this.id); - if (sVerbose) { - Slog.v(TAG, "updateLocked(" + this.id + "): id=" + id + ", action=" - + actionAsString(action) + ", flags=" + flags); - } ViewState viewState = mViewStates.get(id); if (sVerbose) { - Slog.v(TAG, "updateLocked(" + this.id + "): mCurrentViewId=" + mCurrentViewId - + ", mExpiredResponse=" + mSessionFlags.mExpiredResponse - + ", viewState=" + viewState); + Slog.v( + TAG, + "updateLocked(" + id + "): " + + "id=" + this.id + + ", action=" + actionAsString(action) + + ", flags=" + flags + + ", mCurrentViewId=" + mCurrentViewId + + ", mExpiredResponse=" + mSessionFlags.mExpiredResponse + + ", viewState=" + viewState); } if (viewState == null) { @@ -4505,14 +4509,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mSessionFlags.mFillDialogDisabled = true; mPreviouslyFillDialogPotentiallyStarted = false; } else { - // Set the default reason for now if the user doesn't trigger any focus event - // on the autofillable view. This can be changed downstream when more - // information is available or session is committed. - mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( - NOT_SHOWN_REASON_NO_FOCUS); mPreviouslyFillDialogPotentiallyStarted = true; } - requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_SESSION, flags); + Optional<Integer> maybeRequestId = + requestNewFillResponseLocked( + viewState, ViewState.STATE_STARTED_SESSION, flags); + if (maybeRequestId.isPresent()) { + mPresentationStatsEventLogger.maybeSetRequestId(maybeRequestId.get()); + } break; case ACTION_VALUE_CHANGED: if (mCompatMode && (viewState.getState() & ViewState.STATE_URL_BAR) != 0) { @@ -4577,8 +4581,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } boolean isCredmanRequested = (flags & FLAG_VIEW_REQUESTS_CREDMAN_SERVICE) != 0; if (shouldRequestSecondaryProvider(flags)) { - if (requestNewFillResponseOnViewEnteredIfNecessaryLocked( - id, viewState, flags)) { + Optional<Integer> maybeRequestIdCred = + requestNewFillResponseOnViewEnteredIfNecessaryLocked( + id, viewState, flags); + if (maybeRequestIdCred.isPresent()) { Slog.v(TAG, "Started a new fill request for secondary provider."); return; } @@ -4622,17 +4628,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mLogViewEntered = true; } - // Previously, fill request will only start whenever a view is entered. - // With Fill Dialog, request starts prior to view getting entered. So, we can't end - // the event at this moment, otherwise we will be wrongly attributing fill dialog - // event as concluded. - if (!wasPreviouslyFillDialog && !isSameViewAgain) { - // TODO(b/319872477): Re-consider this logic below - mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( - NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED); - mPresentationStatsEventLogger.logAndEndEvent(); - } - + // Trigger augmented autofill if applicable if ((flags & FLAG_MANUAL_REQUEST) == 0) { // Not a manual request if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains( @@ -4658,26 +4654,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } } - // If previous request was FillDialog request, a logger event was already started - if (!wasPreviouslyFillDialog) { + + Optional<Integer> maybeNewRequestId = + requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags); + + // Previously, fill request will only start whenever a view is entered. + // With Fill Dialog, request starts prior to view getting entered. So, we can't end + // the event at this moment, otherwise we will be wrongly attributing fill dialog + // event as concluded. + if (!wasPreviouslyFillDialog + && (!isSameViewEntered || maybeNewRequestId.isPresent())) { startNewEventForPresentationStatsEventLogger(); - } - if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) { - // If a new request was issued even if previously it was fill dialog request, - // we should end the log event, and start a new one. However, it leaves us - // susceptible to race condition. But since mPresentationStatsEventLogger is - // lock guarded, we should be safe. - if (wasPreviouslyFillDialog) { - mPresentationStatsEventLogger.logAndEndEvent(); - startNewEventForPresentationStatsEventLogger(); + if (maybeNewRequestId.isPresent()) { + mPresentationStatsEventLogger.maybeSetRequestId(maybeNewRequestId.get()); } - return; } - FillResponse response = viewState.getResponse(); - if (response != null) { - logPresentationStatsOnViewEnteredLocked(response, isCredmanRequested); - } + logPresentationStatsOnViewEnteredLocked( + viewState.getResponse(), isCredmanRequested); + mPresentationStatsEventLogger.updateTextFieldLength(value); if (isSameViewEntered) { setFillDialogDisabledAndStartInput(); @@ -4719,13 +4714,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private void logPresentationStatsOnViewEnteredLocked(FillResponse response, boolean isCredmanRequested) { - mPresentationStatsEventLogger.maybeSetRequestId(response.getRequestId()); mPresentationStatsEventLogger.maybeSetIsCredentialRequest(isCredmanRequested); mPresentationStatsEventLogger.maybeSetFieldClassificationRequestId( mFieldClassificationIdSnapshot); - mPresentationStatsEventLogger.maybeSetAvailableCount( - response.getDatasets(), mCurrentViewId); + mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); mPresentationStatsEventLogger.maybeSetFocusedId(mCurrentViewId); + + if (response != null) { + mPresentationStatsEventLogger.maybeSetRequestId(response.getRequestId()); + mPresentationStatsEventLogger.maybeSetAvailableCount( + response.getDatasets(), mCurrentViewId); + } } @GuardedBy("mLock") @@ -4796,8 +4795,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState viewState.setCurrentValue(value); final String filterText = textValue; - final AutofillValue filledValue = viewState.getAutofilledValue(); + + if (textValue != null) { + mPresentationStatsEventLogger.onFieldTextUpdated(viewState, value); + } + if (filledValue != null) { if (filledValue.equals(value)) { // When the update is caused by autofilling the view, just update the @@ -4821,9 +4824,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState currentView.maybeCallOnFillReady(flags); } } - if (textValue != null) { - mPresentationStatsEventLogger.onFieldTextUpdated(viewState, textValue.length()); - } if (viewState.id.equals(this.mCurrentViewId) && (viewState.getState() & ViewState.STATE_INLINE_SHOWN) != 0) { @@ -4888,7 +4888,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mSaveEventLogger.logAndEndEvent(); mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("on fill ready"); return; } } @@ -4920,7 +4920,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { final ViewState currentView = mViewStates.get(mCurrentViewId); currentView.setState(ViewState.STATE_FILL_DIALOG_SHOWN); - mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_DIALOG); } // Just show fill dialog once, so disabled after shown. // Note: Cannot disable before requestShowFillDialog() because the method @@ -6086,6 +6085,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void startNewEventForPresentationStatsEventLogger() { synchronized (mLock) { mPresentationStatsEventLogger.startNewEvent(); + // Set the default reason for now if the user doesn't trigger any focus event + // on the autofillable view. This can be changed downstream when more + // information is available or session is committed. + mPresentationStatsEventLogger.maybeSetNoPresentationEventReason( + NOT_SHOWN_REASON_NO_FOCUS); mPresentationStatsEventLogger.maybeSetDetectionPreference( getDetectionPreferenceForLogging()); mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); @@ -6724,7 +6728,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState SystemClock.elapsedRealtime() - mStartTime); mFillRequestEventLogger.logAndEndEvent(); mFillResponseEventLogger.logAndEndEvent(); - mPresentationStatsEventLogger.logAndEndEvent(); + mPresentationStatsEventLogger.logAndEndEvent("log all events"); mSaveEventLogger.logAndEndEvent(); mSessionCommittedEventLogger.logAndEndEvent(); } diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index a10039f9bf6c..2446a6dfee89 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -461,9 +461,9 @@ public final class AutoFillUI { } @Override - public void onShown() { + public void onShown(int datasetsShown) { if (mCallback != null) { - mCallback.onShown(UI_TYPE_DIALOG, response.getDatasets().size()); + mCallback.onShown(UI_TYPE_DIALOG, datasetsShown); } } diff --git a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java index 5a71b895a57c..c7b6be60dd3e 100644 --- a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java @@ -85,7 +85,7 @@ final class DialogFillUi { void onDatasetPicked(@NonNull Dataset dataset); void onDismissed(); void onCanceled(); - void onShown(); + void onShown(int datasetsShown); void startIntentSender(IntentSender intentSender); } @@ -155,7 +155,8 @@ final class DialogFillUi { mDialog.setContentView(decor); setDialogParamsAsBottomSheet(); mDialog.setOnCancelListener((d) -> mCallback.onCanceled()); - mDialog.setOnShowListener((d) -> mCallback.onShown()); + int datasetsShown = (mAdapter != null) ? mAdapter.getCount() : 0; + mDialog.setOnShowListener((d) -> mCallback.onShown(datasetsShown)); show(); } diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 2db54435199b..1be352e8e3da 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -137,11 +137,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS; - private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC = - DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC - | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT - | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; - private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:"; /** @@ -373,9 +368,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS; - if (!Flags.consistentDisplayFlags()) { - flags |= DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC; - } if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) { flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED; } @@ -1254,10 +1246,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub // as the virtual display doesn't have any focused windows. Hence, call this for // associating any input device to the source display if the input device emits any key events. private int getTargetDisplayIdForInput(int displayId) { - if (!Flags.interactiveScreenMirror()) { - return displayId; - } - DisplayManagerInternal displayManager = LocalServices.getService( DisplayManagerInternal.class); int mirroredDisplayId = displayManager.getDisplayIdToMirror(displayId); @@ -1313,9 +1301,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub int displayId; displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, this, gwpc, packageName); - gwpc.setDisplayId(displayId, /* isMirrorDisplay= */ Flags.interactiveScreenMirror() - && mDisplayManagerInternal.getDisplayIdToMirror(displayId) - != Display.INVALID_DISPLAY); + boolean isMirrorDisplay = + mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; + gwpc.setDisplayId(displayId, isMirrorDisplay); boolean showPointer; synchronized (mVirtualDeviceLock) { diff --git a/services/contentcapture/java/com/android/server/contentprotection/OWNERS b/services/contentcapture/java/com/android/server/contentprotection/OWNERS new file mode 100644 index 000000000000..3d09da303b0f --- /dev/null +++ b/services/contentcapture/java/com/android/server/contentprotection/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 1040349 + +include /core/java/android/view/contentprotection/OWNERS + diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index a2bbff026b95..37dddc61a976 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -10,9 +10,6 @@ per-file DisplayThread.java = michaelwr@google.com, ogunwale@google.com # Zram writeback per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com -# Userspace reboot -per-file UserspaceRebootLogger.java = ioffe@google.com, dvander@google.com - # ServiceWatcher per-file ServiceWatcher.java = sooniln@google.com diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java deleted file mode 100644 index 89327b50883c..000000000000 --- a/services/core/java/com/android/server/UserspaceRebootLogger.java +++ /dev/null @@ -1,168 +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.server; - -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED; -import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED; - -import android.os.PowerManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.text.TextUtils; -import android.util.Slog; - -import com.android.internal.util.FrameworkStatsLog; - -import java.util.concurrent.Executor; - -/** - * Utility class to help abstract logging {@code UserspaceRebootReported} atom. - */ -public final class UserspaceRebootLogger { - - private static final String TAG = "UserspaceRebootLogger"; - - private static final String USERSPACE_REBOOT_SHOULD_LOG_PROPERTY = - "persist.sys.userspace_reboot.log.should_log"; - private static final String USERSPACE_REBOOT_LAST_STARTED_PROPERTY = - "sys.userspace_reboot.log.last_started"; - private static final String USERSPACE_REBOOT_LAST_FINISHED_PROPERTY = - "sys.userspace_reboot.log.last_finished"; - private static final String LAST_BOOT_REASON_PROPERTY = "sys.boot.reason.last"; - - private UserspaceRebootLogger() {} - - /** - * Modifies internal state to note that {@code UserspaceRebootReported} atom needs to be - * logged on the next successful boot. - * - * <p>This call should only be made on devices supporting userspace reboot. - */ - public static void noteUserspaceRebootWasRequested() { - if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "noteUserspaceRebootWasRequested: Userspace reboot is not supported."); - return; - } - - SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, "1"); - SystemProperties.set(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, - String.valueOf(SystemClock.elapsedRealtime())); - } - - /** - * Updates internal state on boot after successful userspace reboot. - * - * <p>Should be called right before framework sets {@code sys.boot_completed} property. - * - * <p>This call should only be made on devices supporting userspace reboot. - */ - public static void noteUserspaceRebootSuccess() { - if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "noteUserspaceRebootSuccess: Userspace reboot is not supported."); - return; - } - - SystemProperties.set(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY, - String.valueOf(SystemClock.elapsedRealtime())); - } - - /** - * Returns {@code true} if {@code UserspaceRebootReported} atom should be logged. - * - * <p>On devices that do not support userspace reboot this method will always return {@code - * false}. - */ - public static boolean shouldLogUserspaceRebootEvent() { - if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - return false; - } - - return SystemProperties.getBoolean(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, false); - } - - /** - * Asynchronously logs {@code UserspaceRebootReported} on the given {@code executor}. - * - * <p>Should be called in the end of {@link - * com.android.server.am.ActivityManagerService#finishBooting()} method, after framework have - * tried to proactivelly unlock storage of the primary user. - * - * <p>This call should only be made on devices supporting userspace reboot. - */ - public static void logEventAsync(boolean userUnlocked, Executor executor) { - if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "logEventAsync: Userspace reboot is not supported."); - return; - } - - final int outcome = computeOutcome(); - final long durationMillis; - if (outcome == USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS) { - durationMillis = SystemProperties.getLong(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY, 0) - - SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, 0); - } else { - durationMillis = 0; - } - final int encryptionState = - userUnlocked - ? USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED - : USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED; - executor.execute( - () -> { - Slog.i(TAG, "Logging UserspaceRebootReported atom: { outcome: " + outcome - + " durationMillis: " + durationMillis + " encryptionState: " - + encryptionState + " }"); - FrameworkStatsLog.write(FrameworkStatsLog.USERSPACE_REBOOT_REPORTED, outcome, - durationMillis, encryptionState); - SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, ""); - }); - } - - private static int computeOutcome() { - if (SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, -1) != -1) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS; - } - String reason = TextUtils.emptyIfNull(SystemProperties.get(LAST_BOOT_REASON_PROPERTY, "")); - if (reason.startsWith("reboot,")) { - reason = reason.substring("reboot".length()); - } - if (reason.startsWith("userspace_failed,watchdog_fork")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED; - } - if (reason.startsWith("userspace_failed,shutdown_aborted")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED; - } - if (reason.startsWith("mount_userdata_failed")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; - } - if (reason.startsWith("userspace_failed,init_user0")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; - } - if (reason.startsWith("userspace_failed,enablefilecrypto")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; - } - if (reason.startsWith("userspace_failed,watchdog_triggered")) { - return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED; - } - return USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN; - } -} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4a18cb1f5ed8..68d92218c01b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -372,7 +372,6 @@ import android.os.storage.StorageManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.server.ServerProtoEnums; -import android.sysprop.InitProperties; import android.system.Os; import android.system.OsConstants; import android.telephony.TelephonyManager; @@ -451,7 +450,6 @@ import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; -import com.android.server.UserspaceRebootLogger; import com.android.server.Watchdog; import com.android.server.am.ComponentAliasResolver.Resolution; import com.android.server.am.LowMemDetector.MemFactor; @@ -2360,20 +2358,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - private void maybeLogUserspaceRebootEvent() { - if (!UserspaceRebootLogger.shouldLogUserspaceRebootEvent()) { - return; - } - final int userId = mUserController.getCurrentUserId(); - if (userId != UserHandle.USER_SYSTEM) { - // Only log for user0. - return; - } - // TODO(b/148767783): should we check all profiles under user0? - UserspaceRebootLogger.logEventAsync(StorageManager.isCeStorageUnlocked(userId), - BackgroundThread.getExecutor()); - } - /** * Encapsulates global settings related to hidden API enforcement behaviour, including tracking * the latest value via a content observer. @@ -5323,12 +5307,6 @@ public class ActivityManagerService extends IActivityManager.Stub // Start looking for apps that are abusing wake locks. Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG); mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL); - // Check if we are performing userspace reboot before setting sys.boot_completed to - // avoid race with init reseting sys.init.userspace_reboot.in_progress once sys - // .boot_completed is 1. - if (InitProperties.userspace_reboot_in_progress().orElse(false)) { - UserspaceRebootLogger.noteUserspaceRebootSuccess(); - } // Tell anyone interested that we are done booting! SystemProperties.set("sys.boot_completed", "1"); SystemProperties.set("dev.bootcomplete", "1"); @@ -5352,7 +5330,6 @@ public class ActivityManagerService extends IActivityManager.Stub }, mConstants.FULL_PSS_MIN_INTERVAL); } }); - maybeLogUserspaceRebootEvent(); mUserController.scheduleStartProfiles(); } // UART is on if init's console service is running, send a warning notification. @@ -15335,12 +15312,17 @@ public class ActivityManagerService extends IActivityManager.Stub final int cookie = traceBroadcastIntentBegin(intent, resultTo, ordered, sticky, callingUid, realCallingUid, userId); try { + final BroadcastSentEventRecord broadcastSentEventRecord = + new BroadcastSentEventRecord(); final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras, requiredPermissions, excludedPermissions, excludedPackages, appOp, BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId, - backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver); + backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver, + broadcastSentEventRecord); + broadcastSentEventRecord.setResult(res); + broadcastSentEventRecord.logToStatsd(); return res; } finally { traceBroadcastIntentEnd(cookie); @@ -15388,7 +15370,8 @@ public class ActivityManagerService extends IActivityManager.Stub int callingUid, int realCallingUid, int realCallingPid, int userId, BackgroundStartPrivileges backgroundStartPrivileges, @Nullable int[] broadcastAllowList, - @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) { + @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, + @NonNull BroadcastSentEventRecord broadcastSentEventRecord) { // Ensure all internal loopers are registered for idle checks BroadcastLoopers.addMyLooper(); @@ -15421,6 +15404,17 @@ public class ActivityManagerService extends IActivityManager.Stub } intent = new Intent(intent); + broadcastSentEventRecord.setIntent(intent); + broadcastSentEventRecord.setOriginalIntentFlags(intent.getFlags()); + broadcastSentEventRecord.setSenderUid(callingUid); + broadcastSentEventRecord.setRealSenderUid(realCallingUid); + broadcastSentEventRecord.setSticky(sticky); + broadcastSentEventRecord.setOrdered(ordered); + broadcastSentEventRecord.setResultRequested(resultTo != null); + final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); + broadcastSentEventRecord.setSenderProcState(callerAppProcessState); + broadcastSentEventRecord.setSenderUidState(getRealUidStateLocked(callerApp, + realCallingPid)); final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid); // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS @@ -15914,7 +15908,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid); // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, @@ -16154,6 +16147,7 @@ public class ActivityManagerService extends IActivityManager.Stub ordered, sticky, false, userId, backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver, callerAppProcessState); + broadcastSentEventRecord.setBroadcastRecord(r); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r); queue.enqueueBroadcastLocked(r); @@ -16210,6 +16204,22 @@ public class ActivityManagerService extends IActivityManager.Stub return PROCESS_STATE_NONEXISTENT; } + @GuardedBy("this") + private int getRealUidStateLocked(ProcessRecord app, int pid) { + if (app == null) { + synchronized (mPidsSelfLocked) { + app = mPidsSelfLocked.get(pid); + } + } + if (app != null && app.getThread() != null && !app.isKilled()) { + final UidRecord uidRecord = app.getUidRecord(); + if (uidRecord != null) { + return uidRecord.getCurProcState(); + } + } + return PROCESS_STATE_NONEXISTENT; + } + @VisibleForTesting ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) { synchronized (mStickyBroadcasts) { diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index edb04c5c00bc..f908c67d7ec9 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -53,6 +53,7 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.IntArray; import android.util.PrintWriterPrinter; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -940,6 +941,46 @@ final class BroadcastRecord extends Binder { return type; } + int[] calculateTypesForLogging() { + final IntArray types = new IntArray(); + if (isForeground()) { + types.add(BROADCAST_TYPE_FOREGROUND); + } else { + types.add(BROADCAST_TYPE_BACKGROUND); + } + if (alarm) { + types.add(BROADCAST_TYPE_ALARM); + } + if (interactive) { + types.add(BROADCAST_TYPE_INTERACTIVE); + } + if (ordered) { + types.add(BROADCAST_TYPE_ORDERED); + } + if (prioritized) { + types.add(BROADCAST_TYPE_PRIORITIZED); + } + if (resultTo != null) { + types.add(BROADCAST_TYPE_RESULT_TO); + } + if (deferUntilActive) { + types.add(BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE); + } + if (pushMessage) { + types.add(BROADCAST_TYPE_PUSH_MESSAGE); + } + if (pushMessageOverQuota) { + types.add(BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA); + } + if (sticky) { + types.add(BROADCAST_TYPE_STICKY); + } + if (initialSticky) { + types.add(BROADCAST_TYPE_INITIAL_STICKY); + } + return types.toArray(); + } + public BroadcastRecord maybeStripForHistory() { if (!intent.canStripForHistory()) { return this; diff --git a/services/core/java/com/android/server/am/BroadcastSentEventRecord.java b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java new file mode 100644 index 000000000000..f2ac6d52b0c0 --- /dev/null +++ b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED; +import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO; +import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY; + +import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT; +import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; +import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; +import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__SUCCESS; +import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__UNKNOWN; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Intent; +import android.util.IntArray; + +import com.android.internal.util.FrameworkStatsLog; + +final class BroadcastSentEventRecord { + @NonNull private Intent mIntent; + private int mOriginalIntentFlags; + private int mSenderUid; + private int mRealSenderUid; + private boolean mSticky; + private boolean mOrdered; + private boolean mResultRequested; + private int mSenderProcState; + private int mSenderUidState; + @Nullable private BroadcastRecord mBroadcastRecord; + private int mResult; + + public void setIntent(@NonNull Intent intent) { + mIntent = intent; + } + + public void setSenderUid(int uid) { + mSenderUid = uid; + } + + public void setRealSenderUid(int uid) { + mRealSenderUid = uid; + } + + public void setOriginalIntentFlags(int flags) { + mOriginalIntentFlags = flags; + } + + public void setSticky(boolean sticky) { + mSticky = sticky; + } + + public void setOrdered(boolean ordered) { + mOrdered = ordered; + } + + public void setResultRequested(boolean resultRequested) { + mResultRequested = resultRequested; + } + + public void setSenderProcState(int procState) { + mSenderProcState = procState; + } + + public void setSenderUidState(int procState) { + mSenderUidState = procState; + } + + public void setBroadcastRecord(@NonNull BroadcastRecord record) { + mBroadcastRecord = record; + } + + public void setResult(int result) { + mResult = result; + } + + public void logToStatsd() { + if (Flags.logBroadcastSentEvent()) { + int loggingResult = switch (mResult) { + case ActivityManager.BROADCAST_SUCCESS -> + BROADCAST_SENT__RESULT__SUCCESS; + case ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION -> + BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION; + case ActivityManager.BROADCAST_FAILED_USER_STOPPED -> + BROADCAST_SENT__RESULT__FAILED_USER_STOPPED; + default -> BROADCAST_SENT__RESULT__UNKNOWN; + }; + int[] types = calculateTypesForLogging(); + FrameworkStatsLog.write(BROADCAST_SENT, mIntent.getAction(), mIntent.getFlags(), + mOriginalIntentFlags, mSenderUid, mRealSenderUid, mIntent.getPackage() != null, + mIntent.getComponent() != null, + mBroadcastRecord != null ? mBroadcastRecord.receivers.size() : 0, + loggingResult, + mBroadcastRecord != null ? mBroadcastRecord.getDeliveryGroupPolicy() : 0, + ActivityManager.processStateAmToProto(mSenderProcState), + ActivityManager.processStateAmToProto(mSenderUidState), types); + } + } + + private int[] calculateTypesForLogging() { + if (mBroadcastRecord != null) { + return mBroadcastRecord.calculateTypesForLogging(); + } else { + final IntArray types = new IntArray(); + if (mSticky) { + types.add(BROADCAST_TYPE_STICKY); + } + if (mOrdered) { + types.add(BROADCAST_TYPE_ORDERED); + } + if (mResultRequested) { + types.add(BROADCAST_TYPE_RESULT_TO); + } + return types.toArray(); + } + } +} diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig index 5315167b46eb..3334393a1618 100644 --- a/services/core/java/com/android/server/am/flags.aconfig +++ b/services/core/java/com/android/server/am/flags.aconfig @@ -184,3 +184,14 @@ flag { description: "Defer submitting binder calls to paused processes." bug: "327038797" } + +flag { + name: "log_broadcast_sent_event" + namespace: "backstage_power" + description: "Log the broadcast send event to Statsd" + bug: "355261986" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index f61bd6040658..154b52b86e73 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -1413,6 +1413,22 @@ public class AppOpsService extends IAppOpsService.Stub { } public void uidRemoved(int uid) { + if (Flags.dontRemoveExistingUidStates()) { + // b/358365471 If apps sharing UID are installed on multiple users and only one of + // them is installed for a single user while keeping the others we observe this + // subroutine get invoked incorrectly since the UID still exists. + final long token = Binder.clearCallingIdentity(); + try { + String uidName = getPackageManagerInternal().getNameForUid(uid); + if (uidName != null) { + Slog.e(TAG, "Tried to remove existing UID. uid: " + uid + " name: " + uidName); + return; + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + synchronized (this) { if (mUidStates.indexOfKey(uid) >= 0) { mUidStates.get(uid).clear(); diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index 0bd22f3da67f..f0da67bd9f9a 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -77,13 +77,15 @@ class PreAuthInfo { private final int mBiometricStrengthRequested; private final BiometricCameraManager mBiometricCameraManager; private final boolean mOnlyMandatoryBiometricsRequested; + private final boolean mIsMandatoryBiometricsAuthentication; private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, PromptInfo promptInfo, int userId, Context context, BiometricCameraManager biometricCameraManager, - boolean isOnlyMandatoryBiometricsRequested) { + boolean isOnlyMandatoryBiometricsRequested, + boolean isMandatoryBiometricsAuthentication) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; mBiometricCameraManager = biometricCameraManager; @@ -97,6 +99,7 @@ class PreAuthInfo { this.userId = userId; this.context = context; this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested; + this.mIsMandatoryBiometricsAuthentication = isMandatoryBiometricsAuthentication; } static PreAuthInfo create(ITrustManager trustManager, @@ -110,10 +113,12 @@ class PreAuthInfo { final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators() == BiometricManager.Authenticators.MANDATORY_BIOMETRICS; + boolean isMandatoryBiometricsAuthentication = false; if (dropCredentialFallback(promptInfo.getAuthenticators(), settingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser( userId), trustManager)) { + isMandatoryBiometricsAuthentication = true; promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); promptInfo.setNegativeButtonText(context.getString(R.string.cancel)); } @@ -166,7 +171,8 @@ class PreAuthInfo { return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, userId, - context, biometricCameraManager, isOnlyMandatoryBiometricsRequested); + context, biometricCameraManager, isOnlyMandatoryBiometricsRequested, + isMandatoryBiometricsAuthentication); } private static boolean dropCredentialFallback(int authenticators, @@ -387,25 +393,6 @@ class PreAuthInfo { status = CREDENTIAL_NOT_ENROLLED; } } - } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested) { - if (!eligibleSensors.isEmpty()) { - for (BiometricSensor sensor : eligibleSensors) { - modality |= sensor.modality; - } - - if (modality == TYPE_FACE && cameraPrivacyEnabled) { - // If the only modality requested is face, credential is unavailable, - // and the face sensor privacy is enabled then return - // BIOMETRIC_SENSOR_PRIVACY_ENABLED. - // - // Note: This sensor will not be eligible for calls to authenticate. - status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; - } else { - status = AUTHENTICATOR_OK; - } - } else { - status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; - } } else if (mBiometricRequested) { if (!eligibleSensors.isEmpty()) { for (BiometricSensor sensor : eligibleSensors) { @@ -434,6 +421,9 @@ class PreAuthInfo { } else if (credentialRequested) { modality |= TYPE_CREDENTIAL; status = credentialAvailable ? AUTHENTICATOR_OK : CREDENTIAL_NOT_ENROLLED; + } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested + && !mIsMandatoryBiometricsAuthentication) { + status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; } else { // This should not be possible via the public API surface and is here mainly for // "correctness". An exception should have been thrown before getting here. diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java index fb8a81be4b89..871121472938 100644 --- a/services/core/java/com/android/server/biometrics/Utils.java +++ b/services/core/java/com/android/server/biometrics/Utils.java @@ -35,6 +35,7 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED; import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED; +import static com.android.server.biometrics.PreAuthInfo.MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; import android.annotation.NonNull; import android.annotation.Nullable; @@ -48,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorProperties; @@ -309,11 +311,16 @@ public class Utils { break; case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: - biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS; + biometricManagerCode = Flags.mandatoryBiometrics() + ? BiometricManager.BIOMETRIC_ERROR_LOCKOUT + : BiometricManager.BIOMETRIC_SUCCESS; break; case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; break; + case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE: + biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; + break; default: Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; @@ -375,6 +382,8 @@ public class Utils { return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; case BIOMETRIC_SENSOR_PRIVACY_ENABLED: return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; + case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR: + return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: case BIOMETRIC_HARDWARE_NOT_DETECTED: case BIOMETRIC_NOT_ENABLED_FOR_APPS: diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java index f31b2e11b021..2c52e3d8ca67 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java @@ -241,6 +241,14 @@ public class BiometricFrameworkStatsLogger { -1 /* sensorId */); } + /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ + public void reportFingerprintsLoe(int statsModality) { + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + statsModality, + BiometricsProtoEnums.ISSUE_FINGERPRINTS_LOE, + -1 /* sensorId */); + } + /** {@see FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION}. */ public void logFrameworkNotification(int action, int modality) { FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION, diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java index ff1e5d5f91e6..9351bc0811f2 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java @@ -296,6 +296,15 @@ public class BiometricLogger { mSink.reportUnknownTemplateEnrolledFramework(mStatsModality); } + /** Report unknown enrollment in framework settings */ + public void logFingerprintsLoe() { + if (shouldSkipLogging()) { + return; + } + + mSink.reportFingerprintsLoe(mStatsModality); + } + /** * Get a callback to start/stop ALS capture when the client runs. Do not create * multiple callbacks since there is at most one light sensor (they will all share diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java index 77e27ba4df02..7bd905b4524a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java @@ -161,6 +161,11 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide getLogger().logUnknownEnrollmentInHal(); + if (mBiometricUtils.hasValidBiometricUserState(getContext(), getTargetUserId()) + && Flags.notifyFingerprintsLoe()) { + getLogger().logFingerprintsLoe(); + } + mCurrentTask.start(mRemoveCallback); } diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java index 38e6d822477a..1094bee1e7e6 100644 --- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java @@ -1002,9 +1002,9 @@ public final class DeviceStateManagerService extends SystemService { /** * Checks if the process can cancel a device state request. If the calling process ID is not - * both the top app and foregrounded nor does the process ID and userID match the IDs that made - * the device state request, then check if this process holds the CONTROL_DEVICE_STATE - * permission. + * both the top app and foregrounded, verify that the calling process is in the foreground and + * that it matches the process ID and user ID that made the device state request. If neither are + * true, then check if this process holds the CONTROL_DEVICE_STATE permission. * * @param callingPid Process ID that is requesting this state change * @param callingUid UID that is requesting this state change @@ -1018,8 +1018,8 @@ public final class DeviceStateManagerService extends SystemService { if (Flags.deviceStateRequesterCancelState()) { synchronized (mLock) { isAllowedToControlState = - isAllowedToControlState || doCallingIdsMatchOverrideRequestIdsLocked( - callingPid, callingUid); + isTopApp || (isForegroundApp && doCallingIdsMatchOverrideRequestIdsLocked( + callingPid, callingUid)); } } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 226bdf54ce3b..240e91bccaca 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; + import static com.android.server.display.BrightnessMappingStrategy.INVALID_LUX; import static com.android.server.display.config.DisplayBrightnessMappingConfig.autoBrightnessModeToString; @@ -241,6 +243,9 @@ public class AutomaticBrightnessController { private int mDisplayState = Display.STATE_UNKNOWN; + // True if the normal brightness should be forced while device is dozing. + private boolean mUseNormalBrightnessForDoze; + // True if we are collecting a brightness adjustment sample, along with some data // for the initial state of the sample. private boolean mBrightnessAdjustmentSamplePending; @@ -442,11 +447,12 @@ public class AutomaticBrightnessController { public void configure(int state, @Nullable BrightnessConfiguration configuration, float brightness, boolean userChangedBrightness, float adjustment, boolean userChangedAutoBrightnessAdjustment, int displayPolicy, int displayState, - boolean shouldResetShortTermModel) { + boolean useNormalBrightnessForDoze, boolean shouldResetShortTermModel) { mState = state; boolean changed = setBrightnessConfiguration(configuration, shouldResetShortTermModel); changed |= setDisplayPolicy(displayPolicy); mDisplayState = displayState; + mUseNormalBrightnessForDoze = useNormalBrightnessForDoze; if (userChangedAutoBrightnessAdjustment) { changed |= setAutoBrightnessAdjustment(adjustment); } @@ -1264,11 +1270,10 @@ public class AutomaticBrightnessController { } private boolean shouldApplyDozeScaleFactor() { - // Apply the doze scale factor if the display is in doze. We shouldn't rely on the display - // policy here - the screen might turn on while the policy is POLICY_DOZE and in this - // situation, we shouldn't apply the doze scale factor. We also don't apply the doze scale - // factor if we have a designated brightness curve for doze. - return Display.isDozeState(mDisplayState) && getMode() != AUTO_BRIGHTNESS_MODE_DOZE; + // We don't apply the doze scale factor if we have a designated brightness curve for doze. + return (mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled() + ? !mUseNormalBrightnessForDoze && mDisplayPolicy == POLICY_DOZE + : Display.isDozeState(mDisplayState)) && getMode() != AUTO_BRIGHTNESS_MODE_DOZE; } private class ShortTermModel { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 9e905abd78ed..55a6ce7142f3 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -64,7 +64,6 @@ import android.app.AppOpsManager; import android.app.compat.CompatChanges; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.flags.Flags; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.BroadcastReceiver; @@ -1633,8 +1632,7 @@ public final class DisplayManagerService extends SystemService { && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { // Only a valid media projection or a virtual device can create a mirror virtual // display. - if (!canProjectVideo(projection) - && !isMirroringSupportedByVirtualDevice(virtualDevice)) { + if (!canProjectVideo(projection) && virtualDevice == null) { throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " + "MediaProjection token in order to create a screen sharing virtual " @@ -1896,10 +1894,6 @@ public final class DisplayManagerService extends SystemService { return -1; } - private static boolean isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice) { - return Flags.interactiveScreenMirror() && virtualDevice != null; - } - private void resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi) { synchronized (mSyncRoot) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 8bb33ddb84ae..ab7971355041 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -492,6 +492,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Used to scale the brightness in doze mode private float mDozeScaleFactor; + // Used to keep track of the display state from the latest request to override the doze screen + // state. + @GuardedBy("mLock") + private int mPendingOverrideDozeScreenStateLocked; + /** * Creates the display power controller. */ @@ -803,15 +808,28 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @Override public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) { Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState)); - mHandler.postAtTime(() -> { - if (mDisplayOffloadSession == null - || !(DisplayOffloadSession.isSupportedOffloadState(displayState) - || displayState == Display.STATE_UNKNOWN)) { - return; + if (mDisplayOffloadSession != null + && (DisplayOffloadSession.isSupportedOffloadState(displayState) + || displayState == Display.STATE_UNKNOWN)) { + if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { + mWakelockController.acquireWakelock( + WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); } - mDisplayStateController.overrideDozeScreenState(displayState, reason); - updatePowerState(); - }, mClock.uptimeMillis()); + synchronized (mLock) { + mPendingOverrideDozeScreenStateLocked = displayState; + } + mHandler.postAtTime(() -> { + synchronized (mLock) { + mDisplayStateController + .overrideDozeScreenState(mPendingOverrideDozeScreenStateLocked, reason); + } + updatePowerState(); + if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { + mWakelockController.releaseWakelock( + WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE); + } + }, mClock.uptimeMillis()); + } } @Override @@ -1338,30 +1356,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN); } - if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) { - // Sometimes, a display-state change can come without an associated PowerRequest, - // as with DisplayOffload. For those cases, we have to make sure to also mark the - // display as "not ready" so that we can inform power-manager when the state-change is - // complete. - if (mPowerState.getScreenState() != state) { - final boolean wasReady; - synchronized (mLock) { - wasReady = mDisplayReadyLocked; - mDisplayReadyLocked = false; - mustNotify = true; - } - - if (wasReady) { - // If we went from ready to not-ready from the state-change (instead of a - // PowerRequest) there's a good chance that nothing is keeping PowerManager - // from suspending. Grab the unfinished business suspend blocker to keep the - // device awake until the display-state change goes into effect. - mWakelockController.acquireWakelock( - WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS); - } - } - } - // Animate the screen state change unless already animating. // The transition may be deferred, so after this point we will use the // actual state instead of the desired one. @@ -1419,7 +1413,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mAutomaticBrightnessStrategy.setAutoBrightnessState(state, allowAutoBrightnessWhileDozing, mBrightnessReasonTemp.getReason(), - mPowerRequest.policy, + mPowerRequest.policy, mPowerRequest.useNormalBrightnessForDoze, mDisplayBrightnessController.getLastUserSetScreenBrightness(), userSetBrightnessChanged); @@ -1485,7 +1479,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call brightnessState = clampScreenBrightness(brightnessState); } - if (Display.isDozeState(state)) { + if (mFlags.isNormalBrightnessForDozeParameterEnabled() + ? !mPowerRequest.useNormalBrightnessForDoze && mPowerRequest.policy == POLICY_DOZE + : Display.isDozeState(state)) { // TODO(b/329676661): Introduce a config property to choose between this brightness // strategy and DOZE_DEFAULT // On some devices, when auto-brightness is disabled and the device is dozing, we use @@ -1506,7 +1502,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } // Use default brightness when dozing unless overridden. - if (Float.isNaN(brightnessState) && Display.isDozeState(state) + if (Float.isNaN(brightnessState) && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()) { rawBrightnessState = mScreenBrightnessDozeConfig; brightnessState = clampScreenBrightness(rawBrightnessState); diff --git a/services/core/java/com/android/server/display/WakelockController.java b/services/core/java/com/android/server/display/WakelockController.java index 7bc797125b0e..5b0229cbb393 100644 --- a/services/core/java/com/android/server/display/WakelockController.java +++ b/services/core/java/com/android/server/display/WakelockController.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.hardware.display.DisplayManagerInternal; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.utils.DebugUtils; @@ -37,7 +38,8 @@ public final class WakelockController { public static final int WAKE_LOCK_PROXIMITY_NEGATIVE = 2; public static final int WAKE_LOCK_PROXIMITY_DEBOUNCE = 3; public static final int WAKE_LOCK_STATE_CHANGED = 4; - public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 5; + public static final int WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE = 5; + public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 6; @VisibleForTesting static final int WAKE_LOCK_MAX = WAKE_LOCK_UNFINISHED_BUSINESS; @@ -53,18 +55,23 @@ public final class WakelockController { WAKE_LOCK_PROXIMITY_NEGATIVE, WAKE_LOCK_PROXIMITY_DEBOUNCE, WAKE_LOCK_STATE_CHANGED, + WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, WAKE_LOCK_UNFINISHED_BUSINESS }) @Retention(RetentionPolicy.SOURCE) public @interface WAKE_LOCK_TYPE { } + private final Object mLock = new Object(); + // Asynchronous callbacks into the power manager service. // Only invoked from the handler thread while no locks are held. private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; // Identifiers for suspend blocker acquisition requests private final String mSuspendBlockerIdUnfinishedBusiness; + @GuardedBy("mLock") + private final String mSuspendBlockerOverrideDozeScreenState; private final String mSuspendBlockerIdOnStateChanged; private final String mSuspendBlockerIdProxPositive; private final String mSuspendBlockerIdProxNegative; @@ -73,6 +80,10 @@ public final class WakelockController { // True if we have unfinished business and are holding a suspend-blocker. private boolean mUnfinishedBusiness; + // True if we have are holding a suspend-blocker to override the doze screen state. + @GuardedBy("mLock") + private boolean mIsOverrideDozeScreenStateAcquired; + // True if we have have debounced the proximity change impact and are holding a suspend-blocker. private boolean mHasProximityDebounced; @@ -108,6 +119,7 @@ public final class WakelockController { mTag = TAG + "[" + mDisplayId + "]"; mDisplayPowerCallbacks = callbacks; mSuspendBlockerIdUnfinishedBusiness = "[" + displayId + "]unfinished business"; + mSuspendBlockerOverrideDozeScreenState = "[" + displayId + "]override doze screen state"; mSuspendBlockerIdOnStateChanged = "[" + displayId + "]on state changed"; mSuspendBlockerIdProxPositive = "[" + displayId + "]prox positive"; mSuspendBlockerIdProxNegative = "[" + displayId + "]prox negative"; @@ -154,6 +166,10 @@ public final class WakelockController { return acquireProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return acquireStateChangedSuspendBlocker(); + case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: + synchronized (mLock) { + return acquireOverrideDozeScreenStateSuspendBlockerLocked(); + } case WAKE_LOCK_UNFINISHED_BUSINESS: return acquireUnfinishedBusinessSuspendBlocker(); default: @@ -171,6 +187,10 @@ public final class WakelockController { return releaseProxDebounceSuspendBlocker(); case WAKE_LOCK_STATE_CHANGED: return releaseStateChangedSuspendBlocker(); + case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE: + synchronized (mLock) { + return releaseOverrideDozeScreenStateSuspendBlockerLocked(); + } case WAKE_LOCK_UNFINISHED_BUSINESS: return releaseUnfinishedBusinessSuspendBlocker(); default: @@ -220,6 +240,42 @@ public final class WakelockController { } /** + * Acquires the suspend blocker to override the doze screen state and notifies the + * PowerManagerService about the changes. Note that this utility is syncronized because a + * request to override the doze screen state can come from a non-power thread. + */ + @GuardedBy("mLock") + private boolean acquireOverrideDozeScreenStateSuspendBlockerLocked() { + // Grab a wake lock if we have unfinished business. + if (!mIsOverrideDozeScreenStateAcquired) { + if (DEBUG) { + Slog.d(mTag, "Acquiring suspend blocker to override the doze screen state..."); + } + mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); + mIsOverrideDozeScreenStateAcquired = true; + return true; + } + return false; + } + + /** + * Releases the override doze screen state suspend blocker and notifies the PowerManagerService + * about the changes. + */ + @GuardedBy("mLock") + private boolean releaseOverrideDozeScreenStateSuspendBlockerLocked() { + if (mIsOverrideDozeScreenStateAcquired) { + if (DEBUG) { + Slog.d(mTag, "Finished overriding doze screen state..."); + } + mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerOverrideDozeScreenState); + mIsOverrideDozeScreenStateAcquired = false; + return true; + } + return false; + } + + /** * Acquires the unfinished business wakelock and notifies the PowerManagerService about the * changes. */ @@ -366,6 +422,7 @@ public final class WakelockController { pw.println(" mOnStateChangePending=" + isOnStateChangedPending()); pw.println(" mOnProximityPositiveMessages=" + isProximityPositiveAcquired()); pw.println(" mOnProximityNegativeMessages=" + isProximityNegativeAcquired()); + pw.println(" mIsOverrideDozeScreenStateAcquired=" + isOverrideDozeScreenStateAcquired()); } @VisibleForTesting @@ -394,6 +451,13 @@ public final class WakelockController { } @VisibleForTesting + String getSuspendBlockerOverrideDozeScreenState() { + synchronized (mLock) { + return mSuspendBlockerOverrideDozeScreenState; + } + } + + @VisibleForTesting boolean hasUnfinishedBusiness() { return mUnfinishedBusiness; } @@ -417,4 +481,11 @@ public final class WakelockController { boolean hasProximitySensorDebounced() { return mHasProximityDebounced; } + + @VisibleForTesting + boolean isOverrideDozeScreenStateAcquired() { + synchronized (mLock) { + return mIsOverrideDozeScreenStateAcquired; + } + } } diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java index 7835220d5c13..1b49bbc74f92 100644 --- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java +++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManagerInternal; +import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.util.IndentingPrintWriter; import android.util.Slog; import android.view.Display; @@ -167,7 +168,7 @@ public class DisplayBrightnessStrategySelector { StrategySelectionRequest strategySelectionRequest) { DisplayBrightnessStrategy displayBrightnessStrategy = mInvalidBrightnessStrategy; int targetDisplayState = strategySelectionRequest.getTargetDisplayState(); - DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = strategySelectionRequest + DisplayPowerRequest displayPowerRequest = strategySelectionRequest .getDisplayPowerRequest(); setAllowAutoBrightnessWhileDozing(strategySelectionRequest.getDisplayOffloadSession()); if (targetDisplayState == Display.STATE_OFF) { @@ -301,6 +302,7 @@ public class DisplayBrightnessStrategySelector { mAllowAutoBrightnessWhileDozing, BrightnessReason.REASON_UNKNOWN, strategySelectionRequest.getDisplayPowerRequest().policy, + strategySelectionRequest.getDisplayPowerRequest().useNormalBrightnessForDoze, strategySelectionRequest.getLastUserSetScreenBrightness(), strategySelectionRequest.isUserSetBrightnessChanged()); return mAutomaticBrightnessStrategy1.isAutoBrightnessValid(); @@ -331,12 +333,14 @@ public class DisplayBrightnessStrategySelector { /** * Validates if the conditions are met to qualify for the DozeBrightnessStrategy. */ - private boolean shouldUseDozeBrightnessStrategy( - DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) { + private boolean shouldUseDozeBrightnessStrategy(DisplayPowerRequest displayPowerRequest) { // We are not checking the targetDisplayState, but rather relying on the policy because // a user can define a different display state(displayPowerRequest.dozeScreenState) too - // in the request with the Doze policy - return displayPowerRequest.policy == DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE + // in the request with the Doze policy and user might request an override to force certain + // brightness. + return (!mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled() + || !displayPowerRequest.useNormalBrightnessForDoze) + && displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE && !mAllowAutoBrightnessWhileDozing && BrightnessUtils.isValidBrightnessValue(displayPowerRequest.dozeScreenBrightness); } diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java index 706b4a63f31b..bf01f2d9c749 100644 --- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java @@ -131,13 +131,14 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 */ public void setAutoBrightnessState(int targetDisplayState, boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy, - float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) { + boolean useNormalBrightnessForDoze, float lastUserSetScreenBrightness, + boolean userSetBrightnessChanged) { // We are still in the process of updating the power state, so there's no need to trigger // an update again - switchMode(targetDisplayState, /* sendUpdate= */ false); + switchMode(targetDisplayState, useNormalBrightnessForDoze, policy, /* sendUpdate= */ false); - // If the policy is POLICY_DOZE and the display state is STATE_ON, auto-brightness should - // only be enabled if the config allows it + // If the policy is POLICY_DOZE and the display state is not STATE_OFF, auto-brightness + // should only be enabled if the config allows it final boolean autoBrightnessEnabledInDoze = allowAutoBrightnessWhileDozingConfig && policy == POLICY_DOZE && targetDisplayState != Display.STATE_OFF; @@ -157,7 +158,8 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness, - policy, targetDisplayState, mBrightnessConfiguration, autoBrightnessState); + policy, targetDisplayState, useNormalBrightnessForDoze, mBrightnessConfiguration, + autoBrightnessState); mIsConfigured = true; } @@ -344,6 +346,8 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 strategySelectionNotifyRequest.getSelectedDisplayBrightnessStrategy() .getReason(), strategySelectionNotifyRequest.getDisplayPowerRequest().policy, + strategySelectionNotifyRequest.getDisplayPowerRequest() + .useNormalBrightnessForDoze, strategySelectionNotifyRequest.getLastUserSetScreenBrightness(), strategySelectionNotifyRequest.isUserSetBrightnessChanged()); } @@ -469,7 +473,8 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 @VisibleForTesting void accommodateUserBrightnessChanges(boolean userSetBrightnessChanged, float lastUserSetScreenBrightness, int policy, int displayState, - BrightnessConfiguration brightnessConfiguration, int autoBrightnessState) { + boolean useNormalBrightnessForDoze, BrightnessConfiguration brightnessConfiguration, + int autoBrightnessState) { // Update the pending auto-brightness adjustments if any. This typically checks and adjusts // the state of the class if the user moves the brightness slider and has settled to a // different value @@ -485,8 +490,12 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 mAutomaticBrightnessController.configure(autoBrightnessState, brightnessConfiguration, lastUserSetScreenBrightness, - userSetBrightnessChanged, autoBrightnessAdjustment, - mAutoBrightnessAdjustmentChanged, policy, displayState, + userSetBrightnessChanged, + autoBrightnessAdjustment, + mAutoBrightnessAdjustmentChanged, + policy, + displayState, + useNormalBrightnessForDoze, mShouldResetShortTermModel); mShouldResetShortTermModel = false; // We take note if the user brightness point is still being used in the current @@ -494,11 +503,18 @@ public class AutomaticBrightnessStrategy extends AutomaticBrightnessStrategy2 mIsShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints(); } } - private void switchMode(int state, boolean sendUpdate) { + + private void switchMode(int state, boolean useNormalBrightnessForDoze, int policy, + boolean sendUpdate) { if (mDisplayManagerFlags.areAutoBrightnessModesEnabled() && mAutomaticBrightnessController != null && !mAutomaticBrightnessController.isInIdleMode()) { - mAutomaticBrightnessController.switchMode(Display.isDozeState(state) + + boolean shouldUseDozeMode = + mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled() + ? !useNormalBrightnessForDoze && policy == POLICY_DOZE + : Display.isDozeState(state); + mAutomaticBrightnessController.switchMode(shouldUseDozeMode ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT, sendUpdate); } } diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java index c87872cb24cb..5e79565f7c54 100644 --- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java +++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java @@ -108,9 +108,10 @@ public class AutomaticBrightnessStrategy2 { */ public void setAutoBrightnessState(int targetDisplayState, boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy, - float lastUserSetScreenBrightness, boolean userSetBrightnessChanged) { - // If the policy is POLICY_DOZE and the display state is STATE_ON, auto-brightness should - // only be enabled if the config allows it + boolean useNormalBrightnessForDoze, float lastUserSetScreenBrightness, + boolean userSetBrightnessChanged) { + // If the policy is POLICY_DOZE and the display state is not STATE_OFF, auto-brightness + // should only be enabled if the config allows it final boolean autoBrightnessEnabledInDoze = allowAutoBrightnessWhileDozingConfig && policy == POLICY_DOZE && targetDisplayState != Display.STATE_OFF; @@ -120,7 +121,7 @@ public class AutomaticBrightnessStrategy2 { && brightnessReason != BrightnessReason.REASON_OVERRIDE && mAutomaticBrightnessController != null; mAutoBrightnessDisabledDueToDisplayOff = shouldUseAutoBrightness() - && !((targetDisplayState == Display.STATE_ON && policy != POLICY_DOZE) + && !((targetDisplayState == Display.STATE_ON && policy != POLICY_DOZE) || autoBrightnessEnabledInDoze); final int autoBrightnessState = mIsAutoBrightnessEnabled && brightnessReason != BrightnessReason.REASON_FOLLOWER @@ -130,7 +131,8 @@ public class AutomaticBrightnessStrategy2 { : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED; accommodateUserBrightnessChanges(userSetBrightnessChanged, lastUserSetScreenBrightness, - policy, targetDisplayState, mBrightnessConfiguration, autoBrightnessState); + policy, targetDisplayState, useNormalBrightnessForDoze, mBrightnessConfiguration, + autoBrightnessState); } public boolean isAutoBrightnessEnabled() { @@ -367,7 +369,8 @@ public class AutomaticBrightnessStrategy2 { @VisibleForTesting void accommodateUserBrightnessChanges(boolean userSetBrightnessChanged, float lastUserSetScreenBrightness, int policy, int displayState, - BrightnessConfiguration brightnessConfiguration, int autoBrightnessState) { + boolean useNormalBrightnessForDoze, BrightnessConfiguration brightnessConfiguration, + int autoBrightnessState) { // Update the pending auto-brightness adjustments if any. This typically checks and adjusts // the state of the class if the user moves the brightness slider and has settled to a // different value @@ -384,7 +387,10 @@ public class AutomaticBrightnessStrategy2 { brightnessConfiguration, lastUserSetScreenBrightness, userSetBrightnessChanged, autoBrightnessAdjustment, - mAutoBrightnessAdjustmentChanged, policy, displayState, + mAutoBrightnessAdjustmentChanged, + policy, + displayState, + useNormalBrightnessForDoze, mShouldResetShortTermModel); mShouldResetShortTermModel = false; // We take note if the user brightness point is still being used in the current diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index e1934b0df3f1..f0f6db232f13 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -193,6 +193,11 @@ public class DisplayManagerFlags { Flags.FLAG_NEW_HDR_BRIGHTNESS_MODIFIER, Flags::newHdrBrightnessModifier); + private final FlagState mNormalBrightnessForDozeParameter = new FlagState( + Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER, + Flags::normalBrightnessForDozeParameter + ); + /** * @return {@code true} if 'port' is allowed in display layout configuration file. */ @@ -393,6 +398,13 @@ public class DisplayManagerFlags { } /** + * @return Whether the useDozeBrightness parameter should be used + */ + public boolean isNormalBrightnessForDozeParameterEnabled() { + return mNormalBrightnessForDozeParameter.isEnabled(); + } + + /** * dumps all flagstates * @param pw printWriter */ @@ -431,6 +443,7 @@ public class DisplayManagerFlags { pw.println(" " + mOffloadDozeOverrideHoldsWakelock); pw.println(" " + mOffloadSessionCancelBlockScreenOn); pw.println(" " + mNewHdrBrightnessModifier); + pw.println(" " + mNormalBrightnessForDozeParameter); } private static class FlagState { diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index ac5f97fc3661..d92924957242 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -250,6 +250,13 @@ flag { namespace: "display_manager" description: "Define doze brightness in the float scale [0, 1]." bug: "343796384" +} + +flag { + name: "normal_brightness_for_doze_parameter" + namespace: "wear_frameworks" + description: "Feature flag for the parameter specifying whether brightness should be adjusted while dozing." + bug: "343283838" is_fixed_read_only: true } diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index 5e471c82e108..31f5a417171d 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -1592,6 +1592,12 @@ public class DisplayModeDirector { - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, SYNCHRONIZED_REFRESH_RATE_TARGET + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); + mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, + Vote.forRenderFrameRates( + SYNCHRONIZED_REFRESH_RATE_TARGET + - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, + SYNCHRONIZED_REFRESH_RATE_TARGET + + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); } private void removeDisplaysSynchronizedPeakRefreshRate(final int displayId) { @@ -1603,11 +1609,12 @@ public class DisplayModeDirector { return; } mExternalDisplaysConnected.remove(displayId); - if (mExternalDisplaysConnected.size() != 0) { + if (!mExternalDisplaysConnected.isEmpty()) { return; } } mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE, null); + mVotesStorage.updateGlobalVote(Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, null); } private void updateDisplayDeviceConfig(int displayId) { diff --git a/services/core/java/com/android/server/display/mode/Vote.java b/services/core/java/com/android/server/display/mode/Vote.java index 7cbdd13152b5..88ee044810db 100644 --- a/services/core/java/com/android/server/display/mode/Vote.java +++ b/services/core/java/com/android/server/display/mode/Vote.java @@ -92,48 +92,55 @@ interface Vote { // render rate vote can still apply int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9; - // Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz]. + // Restrict all displays physical refresh rate to 60Hz when external display is connected. + // It votes [59Hz, 61Hz]. int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10; + // PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE has a higher priority than + // PRIORITY_SYNCHRONIZED_REFRESH_RATE and will limit render rate to [59Hz, 61Hz]. + // In case physical refresh rate vote discarded (due to physical refresh rate not supported), + // render rate vote can still apply. + int PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE = 11; + // Restrict displays max available resolution and refresh rates. It votes [0, LIMIT] - int PRIORITY_LIMIT_MODE = 11; + int PRIORITY_LIMIT_MODE = 12; // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh // rate to max value (same as for PRIORITY_UDFPS) on lock screen - int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12; + int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 13; // For concurrent displays we want to limit refresh rate on all displays - int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13; + int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 14; // For internal application to limit display modes to specific ids - int PRIORITY_SYSTEM_REQUESTED_MODES = 14; + int PRIORITY_SYSTEM_REQUESTED_MODES = 15; // PRIORITY_LOW_POWER_MODE_MODES limits display modes to specific refreshRate-vsync pairs if // Settings.Global.LOW_POWER_MODE is on. // Lower priority that PRIORITY_LOW_POWER_MODE_RENDER_RATE and if discarded (due to other // higher priority votes), render rate limit can still apply - int PRIORITY_LOW_POWER_MODE_MODES = 15; + int PRIORITY_LOW_POWER_MODE_MODES = 16; // PRIORITY_LOW_POWER_MODE_RENDER_RATE force the render frame rate to [0, 60HZ] if // Settings.Global.LOW_POWER_MODE is on. - int PRIORITY_LOW_POWER_MODE_RENDER_RATE = 16; + int PRIORITY_LOW_POWER_MODE_RENDER_RATE = 17; // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the // higher priority voters' result is a range, it will fix the rate to a single choice. // It's used to avoid refresh rate switches in certain conditions which may result in the // user seeing the display flickering when the switches occur. - int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 17; + int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 18; // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. - int PRIORITY_SKIN_TEMPERATURE = 18; + int PRIORITY_SKIN_TEMPERATURE = 19; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. - int PRIORITY_PROXIMITY = 19; + int PRIORITY_PROXIMITY = 20; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. - int PRIORITY_UDFPS = 20; + int PRIORITY_UDFPS = 21; @IntDef(prefix = { "PRIORITY_" }, value = { PRIORITY_DEFAULT_RENDER_FRAME_RATE, @@ -147,6 +154,7 @@ interface Vote { PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, PRIORITY_SYNCHRONIZED_REFRESH_RATE, + PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE, PRIORITY_LIMIT_MODE, PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE, PRIORITY_LAYOUT_LIMITED_FRAME_RATE, @@ -267,6 +275,8 @@ interface Vote { return "PRIORITY_LIMIT_MODE"; case PRIORITY_SYNCHRONIZED_REFRESH_RATE: return "PRIORITY_SYNCHRONIZED_REFRESH_RATE"; + case PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE: + return "PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE"; case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE: return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE"; case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE: diff --git a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java index 280a7e1e0521..8a8440ba956a 100644 --- a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java +++ b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java @@ -26,6 +26,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.content.res.Resources; +import android.os.UserHandle; import android.util.Slog; import com.android.internal.R; @@ -197,7 +198,8 @@ public class DisplayNotificationManager implements ConnectedDisplayUsbErrorsDete return; } - mNotificationManager.cancel(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID); + mNotificationManager.cancelAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID, + UserHandle.CURRENT); } /** @@ -210,8 +212,8 @@ public class DisplayNotificationManager implements ConnectedDisplayUsbErrorsDete return; } - mNotificationManager.notify(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID, - notification); + mNotificationManager.notifyAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID, + notification, UserHandle.CURRENT); } /** diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index a3b77e897117..19305dedcb06 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -543,12 +543,14 @@ public final class DreamManagerService extends SystemService { } private void startDozingInternal(IBinder token, int screenState, - @Display.StateReason int reason, float screenBrightnessFloat, int screenBrightnessInt) { + @Display.StateReason int reason, float screenBrightnessFloat, int screenBrightnessInt, + boolean useNormalBrightnessForDoze) { Slog.d(TAG, "Dream requested to start dozing: " + token + ", screenState=" + Display.stateToString(screenState) + ", reason=" + Display.stateReasonToString(reason) + ", screenBrightnessFloat=" + screenBrightnessFloat - + ", screenBrightnessInt=" + screenBrightnessInt); + + ", screenBrightnessInt=" + screenBrightnessInt + + ", useNormalBrightnessForDoze=" + useNormalBrightnessForDoze); synchronized (mLock) { if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) { @@ -556,7 +558,8 @@ public final class DreamManagerService extends SystemService { mCurrentDream.dozeScreenBrightness = screenBrightnessInt; mCurrentDream.dozeScreenBrightnessFloat = screenBrightnessFloat; mPowerManagerInternal.setDozeOverrideFromDreamManager( - screenState, reason, screenBrightnessFloat, screenBrightnessInt); + screenState, reason, screenBrightnessFloat, screenBrightnessInt, + useNormalBrightnessForDoze); if (!mCurrentDream.isDozing) { mCurrentDream.isDozing = true; mDozeWakeLock.acquire(); @@ -578,7 +581,8 @@ public final class DreamManagerService extends SystemService { Display.STATE_UNKNOWN, Display.STATE_REASON_DREAM_MANAGER, PowerManager.BRIGHTNESS_INVALID_FLOAT, - PowerManager.BRIGHTNESS_DEFAULT); + PowerManager.BRIGHTNESS_DEFAULT, + /* useNormalBrightnessForDoze= */ false); } } } @@ -1098,7 +1102,8 @@ public final class DreamManagerService extends SystemService { @Override // Binder call public void startDozing( IBinder token, int screenState, @Display.StateReason int reason, - float screenBrightnessFloat, int screeBrightnessInt) { + float screenBrightnessFloat, int screeBrightnessInt, + boolean useNormalBrightnessForDoze) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -1107,7 +1112,7 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { startDozingInternal(token, screenState, reason, screenBrightnessFloat, - screeBrightnessInt); + screeBrightnessInt, useNormalBrightnessForDoze); } finally { Binder.restoreCallingIdentity(ident); } @@ -1116,7 +1121,8 @@ public final class DreamManagerService extends SystemService { @Override // Binder call public void startDozingOneway( IBinder token, int screenState, @Display.StateReason int reason, - float screenBrightnessFloat, int screeBrightnessInt) { + float screenBrightnessFloat, int screeBrightnessInt, + boolean useNormalBrightnessForDoze) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -1125,7 +1131,7 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { startDozingInternal(token, screenState, reason, screenBrightnessFloat, - screeBrightnessInt); + screeBrightnessInt, useNormalBrightnessForDoze); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java index 819b9a166daa..73f18d17d058 100644 --- a/services/core/java/com/android/server/input/InputManagerInternal.java +++ b/services/core/java/com/android/server/input/InputManagerInternal.java @@ -21,7 +21,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.graphics.PointF; import android.hardware.display.DisplayViewport; -import android.hardware.input.KeyboardSystemShortcut; +import android.hardware.input.KeyGestureEvent; import android.os.IBinder; import android.view.InputChannel; import android.view.inputmethod.InputMethodSubtype; @@ -230,18 +230,14 @@ public abstract class InputManagerInternal { public abstract int getLastUsedInputDeviceId(); /** - * Notify Keyboard system shortcut was triggered by the user and handled by the framework. + * Notify key gesture was completed by the user. * - * NOTE: This is just to notify that a system shortcut was triggered. No further action is - * required to execute the said shortcut. This callback is meant for purposes of providing user - * hints or logging, etc. - * - * @param deviceId the device ID of the keyboard using which the shortcut was triggered - * @param keycodes the keys pressed for triggering the shortcut - * @param modifierState the modifier state of the key event that triggered the shortcut - * @param shortcut the shortcut that was triggered + * @param deviceId the device ID of the keyboard using which the event was completed + * @param keycodes the keys pressed for the event + * @param modifierState the modifier state + * @param event the gesture event that was completed * */ - public abstract void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes, - int modifierState, @KeyboardSystemShortcut.SystemShortcut int shortcut); + public abstract void notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState, + @KeyGestureEvent.KeyGestureType int event); } diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index a69c7efc5b21..a8fc8621cbc7 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -48,18 +48,18 @@ import android.hardware.input.IInputDeviceBatteryState; import android.hardware.input.IInputDevicesChangedListener; import android.hardware.input.IInputManager; import android.hardware.input.IInputSensorEventListener; +import android.hardware.input.IKeyGestureEventListener; import android.hardware.input.IKeyboardBacklightListener; -import android.hardware.input.IKeyboardSystemShortcutListener; import android.hardware.input.IStickyModifierStateListener; import android.hardware.input.ITabletModeChangedListener; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.hardware.input.InputSensorInfo; import android.hardware.input.InputSettings; +import android.hardware.input.KeyGestureEvent; import android.hardware.input.KeyGlyphMap; import android.hardware.input.KeyboardLayout; import android.hardware.input.KeyboardLayoutSelectionResult; -import android.hardware.input.KeyboardSystemShortcut; import android.hardware.input.TouchCalibration; import android.hardware.lights.Light; import android.hardware.lights.LightState; @@ -162,7 +162,7 @@ public class InputManagerService extends IInputManager.Stub private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1; private static final int MSG_RELOAD_DEVICE_ALIASES = 2; private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3; - private static final int MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED = 4; + private static final int MSG_KEY_GESTURE_COMPLETED = 4; private static final int DEFAULT_VIBRATION_MAGNITUDE = 192; private static final AdditionalDisplayInputProperties @@ -314,9 +314,7 @@ public class InputManagerService extends IInputManager.Stub // Manages Sticky modifier state private final StickyModifierStateController mStickyModifierStateController; - - // Manages keyboard system shortcut callbacks - private final KeyboardShortcutCallbackHandler mKeyboardShortcutCallbackHandler; + private final KeyGestureController mKeyGestureController; // Manages Keyboard microphone mute led private final KeyboardLedController mKeyboardLedController; @@ -476,7 +474,7 @@ public class InputManagerService extends IInputManager.Stub injector.getLooper(), injector.getUEventManager()) : new KeyboardBacklightControllerInterface() {}; mStickyModifierStateController = new StickyModifierStateController(); - mKeyboardShortcutCallbackHandler = new KeyboardShortcutCallbackHandler(); + mKeyGestureController = new KeyGestureController(); mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(), mNative); mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper()); @@ -2723,33 +2721,32 @@ public class InputManagerService extends IInputManager.Stub } @Override - @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - public void registerKeyboardSystemShortcutListener( - @NonNull IKeyboardSystemShortcutListener listener) { - super.registerKeyboardSystemShortcutListener_enforcePermission(); + @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES) + public void registerKeyGestureEventListener( + @NonNull IKeyGestureEventListener listener) { + super.registerKeyGestureEventListener_enforcePermission(); Objects.requireNonNull(listener); - mKeyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener, + mKeyGestureController.registerKeyGestureEventListener(listener, Binder.getCallingPid()); } @Override - @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_SYSTEM_SHORTCUTS) - public void unregisterKeyboardSystemShortcutListener( - @NonNull IKeyboardSystemShortcutListener listener) { - super.unregisterKeyboardSystemShortcutListener_enforcePermission(); + @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES) + public void unregisterKeyGestureEventListener( + @NonNull IKeyGestureEventListener listener) { + super.unregisterKeyGestureEventListener_enforcePermission(); Objects.requireNonNull(listener); - mKeyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener, + mKeyGestureController.unregisterKeyGestureEventListener(listener, Binder.getCallingPid()); } - private void handleKeyboardSystemShortcutTriggered(int deviceId, - KeyboardSystemShortcut shortcut) { - InputDevice device = getInputDevice(deviceId); - if (device == null || device.isVirtual() || !device.isFullKeyboard()) { + private void handleKeyGestureCompleted(KeyGestureEvent event) { + InputDevice device = getInputDevice(event.getDeviceId()); + if (device == null || device.isVirtual()) { return; } - KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(device, shortcut); - mKeyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(deviceId, shortcut); + KeyboardMetricsCollector.logKeyboardSystemsEventReportedAtom(device, event); + mKeyGestureController.onKeyGestureEvent(event); } /** @@ -2920,10 +2917,9 @@ public class InputManagerService extends IInputManager.Stub boolean inTabletMode = (boolean) args.arg1; deliverTabletModeChanged(whenNanos, inTabletMode); break; - case MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED: - int deviceId = msg.arg1; - KeyboardSystemShortcut shortcut = (KeyboardSystemShortcut) msg.obj; - handleKeyboardSystemShortcutTriggered(deviceId, shortcut); + case MSG_KEY_GESTURE_COMPLETED: + KeyGestureEvent event = (KeyGestureEvent) msg.obj; + handleKeyGestureCompleted(event); } } } @@ -3251,10 +3247,11 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void notifyKeyboardShortcutTriggered(int deviceId, int[] keycodes, int modifierState, - @KeyboardSystemShortcut.SystemShortcut int shortcut) { - mHandler.obtainMessage(MSG_KEYBOARD_SYSTEM_SHORTCUT_TRIGGERED, deviceId, 0, - new KeyboardSystemShortcut(keycodes, modifierState, shortcut)).sendToTarget(); + public void notifyKeyGestureCompleted(int deviceId, int[] keycodes, int modifierState, + @KeyGestureEvent.KeyGestureType int gestureType) { + mHandler.obtainMessage(MSG_KEY_GESTURE_COMPLETED, + new KeyGestureEvent(deviceId, keycodes, modifierState, + gestureType)).sendToTarget(); } } diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java index 000f3122f05a..ef61d02cd999 100644 --- a/services/core/java/com/android/server/input/InputSettingsObserver.java +++ b/services/core/java/com/android/server/input/InputSettingsObserver.java @@ -71,6 +71,8 @@ class InputSettingsObserver extends ContentObserver { (reason) -> updateTouchpadTapToClickEnabled()), Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_DRAGGING), (reason) -> updateTouchpadTapDraggingEnabled()), + Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_VISUALIZER), + (reason) -> updateTouchpadHardwareStateNotificationsEnabled()), Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE), (reason) -> updateTouchpadRightClickZoneEnabled()), Map.entry(Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), @@ -177,6 +179,10 @@ class InputSettingsObserver extends ContentObserver { mNative.setTouchpadTapDraggingEnabled(InputSettings.useTouchpadTapDragging(mContext)); } + private void updateTouchpadHardwareStateNotificationsEnabled() { + mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext)); + } + private void updateTouchpadRightClickZoneEnabled() { mNative.setTouchpadRightClickZoneEnabled(InputSettings.useTouchpadRightClickZone(mContext)); } diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java new file mode 100644 index 000000000000..674d3c448c86 --- /dev/null +++ b/services/core/java/com/android/server/input/KeyGestureController.java @@ -0,0 +1,134 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.input; + +import android.annotation.BinderThread; +import android.hardware.input.IKeyGestureEventListener; +import android.hardware.input.KeyGestureEvent; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; + +/** + * A thread-safe component of {@link InputManagerService} responsible for managing callbacks when a + * key gesture event occurs. + */ +final class KeyGestureController { + + private static final String TAG = "KeyGestureController"; + + // To enable these logs, run: + // 'adb shell setprop log.tag.KeyGestureController DEBUG' (requires restart) + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + // List of currently registered key gesture event listeners keyed by process pid + @GuardedBy("mKeyGestureEventListenerRecords") + private final SparseArray<KeyGestureEventListenerRecord> + mKeyGestureEventListenerRecords = new SparseArray<>(); + + public void onKeyGestureEvent(KeyGestureEvent event) { + if (DEBUG) { + Slog.d(TAG, "Key gesture event occurred, event = " + event); + } + + synchronized (mKeyGestureEventListenerRecords) { + for (int i = 0; i < mKeyGestureEventListenerRecords.size(); i++) { + mKeyGestureEventListenerRecords.valueAt(i).onKeyGestureEvent(event); + } + } + } + + /** Register the key gesture event listener for a process. */ + @BinderThread + public void registerKeyGestureEventListener(IKeyGestureEventListener listener, + int pid) { + synchronized (mKeyGestureEventListenerRecords) { + if (mKeyGestureEventListenerRecords.get(pid) != null) { + throw new IllegalStateException("The calling process has already registered " + + "a KeyGestureEventListener."); + } + KeyGestureEventListenerRecord record = new KeyGestureEventListenerRecord( + pid, listener); + try { + listener.asBinder().linkToDeath(record, 0); + } catch (RemoteException ex) { + throw new RuntimeException(ex); + } + mKeyGestureEventListenerRecords.put(pid, record); + } + } + + /** Unregister the key gesture event listener for a process. */ + @BinderThread + public void unregisterKeyGestureEventListener(IKeyGestureEventListener listener, + int pid) { + synchronized (mKeyGestureEventListenerRecords) { + KeyGestureEventListenerRecord record = + mKeyGestureEventListenerRecords.get(pid); + if (record == null) { + throw new IllegalStateException("The calling process has no registered " + + "KeyGestureEventListener."); + } + if (record.mListener.asBinder() != listener.asBinder()) { + throw new IllegalStateException("The calling process has a different registered " + + "KeyGestureEventListener."); + } + record.mListener.asBinder().unlinkToDeath(record, 0); + mKeyGestureEventListenerRecords.remove(pid); + } + } + + private void onKeyGestureEventListenerDied(int pid) { + synchronized (mKeyGestureEventListenerRecords) { + mKeyGestureEventListenerRecords.remove(pid); + } + } + + // A record of a registered key gesture event listener from one process. + private class KeyGestureEventListenerRecord implements IBinder.DeathRecipient { + public final int mPid; + public final IKeyGestureEventListener mListener; + + KeyGestureEventListenerRecord(int pid, IKeyGestureEventListener listener) { + mPid = pid; + mListener = listener; + } + + @Override + public void binderDied() { + if (DEBUG) { + Slog.d(TAG, "Key gesture event listener for pid " + mPid + " died."); + } + onKeyGestureEventListenerDied(mPid); + } + + public void onKeyGestureEvent(KeyGestureEvent event) { + try { + mListener.onKeyGestureEvent(event.getDeviceId(), event.getKeycodes(), + event.getModifierState(), event.getKeyGestureType()); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to notify process " + mPid + + " that key gesture event occurred, assuming it died.", ex); + binderDied(); + } + } + } +} diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java index 3d2f95105e76..1daf4db699aa 100644 --- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java +++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java @@ -24,9 +24,9 @@ import static android.hardware.input.KeyboardLayoutSelectionResult.layoutSelecti import android.annotation.NonNull; import android.annotation.Nullable; +import android.hardware.input.KeyGestureEvent; import android.hardware.input.KeyboardLayout; import android.hardware.input.KeyboardLayoutSelectionResult.LayoutSelectionCriteria; -import android.hardware.input.KeyboardSystemShortcut; import android.icu.util.ULocale; import android.text.TextUtils; import android.util.Log; @@ -66,14 +66,17 @@ public final class KeyboardMetricsCollector { * defined in "stats/atoms/input/input_extension_atoms.proto" */ public static void logKeyboardSystemsEventReportedAtom(@NonNull InputDevice inputDevice, - @NonNull KeyboardSystemShortcut keyboardSystemShortcut) { + @NonNull KeyGestureEvent keyGestureEvent) { + if (inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) { + return; + } FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED, inputDevice.getVendorId(), inputDevice.getProductId(), - keyboardSystemShortcut.getSystemShortcut(), keyboardSystemShortcut.getKeycodes(), - keyboardSystemShortcut.getModifierState(), inputDevice.getDeviceBus()); + keyGestureEvent.getKeyGestureType(), keyGestureEvent.getKeycodes(), + keyGestureEvent.getModifierState(), inputDevice.getDeviceBus()); if (DEBUG) { - Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemShortcut); + Slog.d(TAG, "Logging Keyboard system event: " + keyGestureEvent); } } diff --git a/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java b/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java deleted file mode 100644 index 092058e6f7d0..000000000000 --- a/services/core/java/com/android/server/input/KeyboardShortcutCallbackHandler.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.input; - -import android.annotation.BinderThread; -import android.hardware.input.IKeyboardSystemShortcutListener; -import android.hardware.input.KeyboardSystemShortcut; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; -import android.util.Slog; -import android.util.SparseArray; - -import com.android.internal.annotations.GuardedBy; - -/** - * A thread-safe component of {@link InputManagerService} responsible for managing callbacks when a - * keyboard shortcut is triggered. - */ -final class KeyboardShortcutCallbackHandler { - - private static final String TAG = "KeyboardShortcut"; - - // To enable these logs, run: - // 'adb shell setprop log.tag.KeyboardShortcutCallbackHandler DEBUG' (requires restart) - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - // List of currently registered keyboard system shortcut listeners keyed by process pid - @GuardedBy("mKeyboardSystemShortcutListenerRecords") - private final SparseArray<KeyboardSystemShortcutListenerRecord> - mKeyboardSystemShortcutListenerRecords = new SparseArray<>(); - - public void onKeyboardSystemShortcutTriggered(int deviceId, - KeyboardSystemShortcut systemShortcut) { - if (DEBUG) { - Slog.d(TAG, "Keyboard system shortcut triggered, deviceId = " + deviceId - + ", systemShortcut = " + systemShortcut); - } - - synchronized (mKeyboardSystemShortcutListenerRecords) { - for (int i = 0; i < mKeyboardSystemShortcutListenerRecords.size(); i++) { - mKeyboardSystemShortcutListenerRecords.valueAt(i).onKeyboardSystemShortcutTriggered( - deviceId, systemShortcut); - } - } - } - - /** Register the keyboard system shortcut listener for a process. */ - @BinderThread - public void registerKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener, - int pid) { - synchronized (mKeyboardSystemShortcutListenerRecords) { - if (mKeyboardSystemShortcutListenerRecords.get(pid) != null) { - throw new IllegalStateException("The calling process has already registered " - + "a KeyboardSystemShortcutListener."); - } - KeyboardSystemShortcutListenerRecord record = new KeyboardSystemShortcutListenerRecord( - pid, listener); - try { - listener.asBinder().linkToDeath(record, 0); - } catch (RemoteException ex) { - throw new RuntimeException(ex); - } - mKeyboardSystemShortcutListenerRecords.put(pid, record); - } - } - - /** Unregister the keyboard system shortcut listener for a process. */ - @BinderThread - public void unregisterKeyboardSystemShortcutListener(IKeyboardSystemShortcutListener listener, - int pid) { - synchronized (mKeyboardSystemShortcutListenerRecords) { - KeyboardSystemShortcutListenerRecord record = - mKeyboardSystemShortcutListenerRecords.get(pid); - if (record == null) { - throw new IllegalStateException("The calling process has no registered " - + "KeyboardSystemShortcutListener."); - } - if (record.mListener.asBinder() != listener.asBinder()) { - throw new IllegalStateException("The calling process has a different registered " - + "KeyboardSystemShortcutListener."); - } - record.mListener.asBinder().unlinkToDeath(record, 0); - mKeyboardSystemShortcutListenerRecords.remove(pid); - } - } - - private void onKeyboardSystemShortcutListenerDied(int pid) { - synchronized (mKeyboardSystemShortcutListenerRecords) { - mKeyboardSystemShortcutListenerRecords.remove(pid); - } - } - - // A record of a registered keyboard system shortcut listener from one process. - private class KeyboardSystemShortcutListenerRecord implements IBinder.DeathRecipient { - public final int mPid; - public final IKeyboardSystemShortcutListener mListener; - - KeyboardSystemShortcutListenerRecord(int pid, IKeyboardSystemShortcutListener listener) { - mPid = pid; - mListener = listener; - } - - @Override - public void binderDied() { - if (DEBUG) { - Slog.d(TAG, "Keyboard system shortcut listener for pid " + mPid + " died."); - } - onKeyboardSystemShortcutListenerDied(mPid); - } - - public void onKeyboardSystemShortcutTriggered(int deviceId, KeyboardSystemShortcut data) { - try { - mListener.onKeyboardSystemShortcutTriggered(deviceId, data.getKeycodes(), - data.getModifierState(), data.getSystemShortcut()); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify process " + mPid - + " that keyboard system shortcut was triggered, assuming it died.", ex); - binderDied(); - } - } - } -} diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java index a9d40bb54f96..69a9f4d88da1 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -135,6 +135,8 @@ interface NativeInputManagerService { void setTouchpadTapDraggingEnabled(boolean enabled); + void setShouldNotifyTouchpadHardwareState(boolean enabled); + void setTouchpadRightClickZoneEnabled(boolean enabled); void setShowTouches(boolean enabled); @@ -395,6 +397,9 @@ interface NativeInputManagerService { public native void setTouchpadTapDraggingEnabled(boolean enabled); @Override + public native void setShouldNotifyTouchpadHardwareState(boolean enabled); + + @Override public native void setTouchpadRightClickZoneEnabled(boolean enabled); @Override diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 1070f2f8faf1..e1b8e9f559ed 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1364,14 +1364,14 @@ class MediaRouter2ServiceImpl { if (manager == null || manager.mLastSessionCreationRequest == null) { Slog.w(TAG, "requestCreateSessionWithRouter2Locked: " + "Ignoring unknown request."); - userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId); + routerRecord.notifySessionCreationFailed(requestId); return; } if (!TextUtils.equals(manager.mLastSessionCreationRequest.mOldSession.getId(), oldSession.getId())) { Slog.w(TAG, "requestCreateSessionWithRouter2Locked: " + "Ignoring unmatched routing session."); - userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId); + routerRecord.notifySessionCreationFailed(requestId); return; } if (!TextUtils.equals(manager.mLastSessionCreationRequest.mRoute.getId(), @@ -1384,7 +1384,7 @@ class MediaRouter2ServiceImpl { } else { Slog.w(TAG, "requestCreateSessionWithRouter2Locked: " + "Ignoring unmatched route."); - userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId); + routerRecord.notifySessionCreationFailed(requestId); return; } } @@ -1396,7 +1396,7 @@ class MediaRouter2ServiceImpl { && !TextUtils.equals(route.getId(), defaultRouteId)) { Slog.w(TAG, "MODIFY_AUDIO_ROUTING permission is required to transfer to" + route); - userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId); + routerRecord.notifySessionCreationFailed(requestId); return; } } @@ -1484,8 +1484,7 @@ class MediaRouter2ServiceImpl { && !TextUtils.equals(route.getId(), defaultRouteId)) { userHandler.sendMessage( obtainMessage( - UserHandler::notifySessionCreationFailedToRouter, - userHandler, + RouterRecord::notifySessionCreationFailed, routerRecord, toOriginalRequestId(DUMMY_REQUEST_ID))); } else { @@ -1762,12 +1761,7 @@ class MediaRouter2ServiceImpl { if (routerRecord == null) { Slog.w(TAG, "requestCreateSessionWithManagerLocked: Ignoring session creation for " + "unknown router."); - try { - managerRecord.mManager.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR); - } catch (RemoteException ex) { - Slog.w(TAG, "requestCreateSessionWithManagerLocked: Failed to notify failure. " - + "Manager probably died."); - } + managerRecord.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR); return; } @@ -1780,10 +1774,8 @@ class MediaRouter2ServiceImpl { "requestCreateSessionWithManagerLocked: Notifying failure for pending" + " session creation request - oldSession: %s, route: %s", lastRequest.mOldSession, lastRequest.mRoute)); - managerRecord.mUserRecord.mHandler.notifyRequestFailedToManager( - managerRecord.mManager, - toOriginalRequestId(lastRequest.mManagerRequestId), - REASON_UNKNOWN_ERROR); + managerRecord.notifyRequestFailed( + toOriginalRequestId(lastRequest.mManagerRequestId), REASON_UNKNOWN_ERROR); } managerRecord.mLastSessionCreationRequest = new SessionCreationRequest(routerRecord, MediaRoute2ProviderService.REQUEST_ID_NONE, uniqueRequestId, @@ -1793,15 +1785,12 @@ class MediaRouter2ServiceImpl { // As a return, media router will request to create a session. routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage( - UserHandler::requestRouterCreateSessionOnHandler, - routerRecord.mUserRecord.mHandler, - uniqueRequestId, + RouterRecord::requestCreateSessionByManager, routerRecord, managerRecord, + uniqueRequestId, oldSession, - route, - transferInitiatorUserHandle, - transferInitiatorPackageName)); + route)); } @GuardedBy("mLock") @@ -2256,6 +2245,71 @@ class MediaRouter2ServiceImpl { } /** + * Notifies the corresponding router of a request failure. + * + * @param requestId The id of the request that failed. + */ + public void notifySessionCreationFailed(int requestId) { + try { + mRouter.notifySessionCreated(requestId, /* sessionInfo= */ null); + } catch (RemoteException ex) { + Slog.w( + TAG, + "Failed to notify router of the session creation failure." + + " Router probably died.", + ex); + } + } + + /** + * Notifies the corresponding router of the release of the given {@link RoutingSessionInfo}. + */ + public void notifySessionReleased(RoutingSessionInfo sessionInfo) { + try { + mRouter.notifySessionReleased(sessionInfo); + } catch (RemoteException ex) { + Slog.w( + TAG, + "Failed to notify router of the session release. Router probably died.", + ex); + } + } + + /** + * Sends the corresponding router a {@link RoutingSessionInfo session} creation request, + * with the given {@link MediaRoute2Info} as the initial member. + * + * <p>Must be called on the thread of the corresponding {@link UserHandler}. + * + * @param managerRecord The record of the manager that made the request. + * @param uniqueRequestId The id of the request. + * @param oldSession The session from which the transfer originated. + * @param route The initial route member of the session to create. + */ + public void requestCreateSessionByManager( + ManagerRecord managerRecord, + long uniqueRequestId, + RoutingSessionInfo oldSession, + MediaRoute2Info route) { + try { + if (route.isSystemRoute() && !hasSystemRoutingPermission()) { + // The router lacks permission to modify system routing, so we hide system + // route info from them. + route = mUserRecord.mHandler.mSystemProvider.getDefaultRoute(); + } + mRouter.requestCreateSessionByManager(uniqueRequestId, oldSession, route); + } catch (RemoteException ex) { + Slog.w( + TAG, + "getSessionHintsForCreatingSessionOnHandler: " + + "Failed to request. Router probably died.", + ex); + managerRecord.notifyRequestFailed( + toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR); + } + } + + /** * Sends the corresponding router an update for the given session. * * <p>Note: These updates are not directly visible to the app. @@ -2360,6 +2414,25 @@ class MediaRouter2ServiceImpl { } } + /** + * Notifies the corresponding manager of a request failure. + * + * <p>Must be called on the thread of the corresponding {@link UserHandler}. + * + * @param requestId The id of the request that failed. + * @param reason The reason of the failure. One of + */ + public void notifyRequestFailed(int requestId, int reason) { + try { + mManager.notifyRequestFailed(requestId, reason); + } catch (RemoteException ex) { + Slog.w( + TAG, + "Failed to notify manager of the request failure. Manager probably died.", + ex); + } + } + private void updateScanningState(@ScanningState int scanningState) { if (mScanningState == scanningState) { return; @@ -2738,30 +2811,6 @@ class MediaRouter2ServiceImpl { return -1; } - private void requestRouterCreateSessionOnHandler( - long uniqueRequestId, - @NonNull RouterRecord routerRecord, - @NonNull ManagerRecord managerRecord, - @NonNull RoutingSessionInfo oldSession, - @NonNull MediaRoute2Info route, - @NonNull UserHandle transferInitiatorUserHandle, - @NonNull String transferInitiatorPackageName) { - try { - if (route.isSystemRoute() && !routerRecord.hasSystemRoutingPermission()) { - // The router lacks permission to modify system routing, so we hide system - // route info from them. - route = mSystemProvider.getDefaultRoute(); - } - routerRecord.mRouter.requestCreateSessionByManager( - uniqueRequestId, oldSession, route); - } catch (RemoteException ex) { - Slog.w(TAG, "getSessionHintsForCreatingSessionOnHandler: " - + "Failed to request. Router probably died.", ex); - notifyRequestFailedToManager(managerRecord.mManager, - toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR); - } - } - private void requestCreateSessionWithRouter2OnHandler( long uniqueRequestId, long managerRequestId, @@ -2774,8 +2823,7 @@ class MediaRouter2ServiceImpl { if (provider == null) { Slog.w(TAG, "requestCreateSessionWithRouter2OnHandler: Ignoring session " + "creation request since no provider found for given route=" + route); - notifySessionCreationFailedToRouter(routerRecord, - toOriginalRequestId(uniqueRequestId)); + routerRecord.notifySessionCreationFailed(toOriginalRequestId(uniqueRequestId)); return; } @@ -3054,7 +3102,7 @@ class MediaRouter2ServiceImpl { + sessionInfo); return; } - notifySessionReleasedToRouter(routerRecord, sessionInfo); + routerRecord.notifySessionReleased(sessionInfo); } private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider, @@ -3073,8 +3121,7 @@ class MediaRouter2ServiceImpl { final int requesterId = toRequesterId(uniqueRequestId); ManagerRecord manager = findManagerWithId(requesterId); if (manager != null) { - notifyRequestFailedToManager( - manager.mManager, toOriginalRequestId(uniqueRequestId), reason); + manager.notifyRequestFailed(toOriginalRequestId(uniqueRequestId), reason); } // Currently, only manager records can get notified of failures. @@ -3109,40 +3156,19 @@ class MediaRouter2ServiceImpl { // Notify the requester about the failure. // The call should be made by either MediaRouter2 or MediaRouter2Manager. if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) { - notifySessionCreationFailedToRouter( - matchingRequest.mRouterRecord, toOriginalRequestId(uniqueRequestId)); + matchingRequest.mRouterRecord.notifySessionCreationFailed( + toOriginalRequestId(uniqueRequestId)); } else { final int requesterId = toRequesterId(matchingRequest.mManagerRequestId); ManagerRecord manager = findManagerWithId(requesterId); if (manager != null) { - notifyRequestFailedToManager(manager.mManager, + manager.notifyRequestFailed( toOriginalRequestId(matchingRequest.mManagerRequestId), reason); } } return true; } - private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord, - int requestId) { - try { - routerRecord.mRouter.notifySessionCreated(requestId, - /* sessionInfo= */ null); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify router of the session creation failure." - + " Router probably died.", ex); - } - } - - private void notifySessionReleasedToRouter(@NonNull RouterRecord routerRecord, - @NonNull RoutingSessionInfo sessionInfo) { - try { - routerRecord.mRouter.notifySessionReleased(sessionInfo); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify router of the session release." - + " Router probably died.", ex); - } - } - private List<IMediaRouter2Manager> getManagers() { final List<IMediaRouter2Manager> managers = new ArrayList<>(); MediaRouter2ServiceImpl service = mServiceRef.get(); @@ -3379,16 +3405,6 @@ class MediaRouter2ServiceImpl { // need to update routers other than the one making the update. } - private void notifyRequestFailedToManager(@NonNull IMediaRouter2Manager manager, - int requestId, int reason) { - try { - manager.notifyRequestFailed(requestId, reason); - } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify manager of the request failure." - + " Manager probably died.", ex); - } - } - private void updateDiscoveryPreferenceOnHandler() { MediaRouter2ServiceImpl service = mServiceRef.get(); if (service == null) { diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java index 1cdab44a5b1b..008746c0423c 100644 --- a/services/core/java/com/android/server/notification/GroupHelper.java +++ b/services/core/java/com/android/server/notification/GroupHelper.java @@ -118,11 +118,32 @@ public class GroupHelper { private final ArrayMap<FullyQualifiedGroupKey, ArrayMap<String, NotificationAttributes>> mAggregatedNotifications = new ArrayMap<>(); - private static final List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS = List.of( - new NotificationSectioner("AlertingSection", 0, (record) -> - record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT), - new NotificationSectioner("SilentSection", 1, (record) -> - record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT)); + private static List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS = + getNotificationShadeSections(); + + private static List<NotificationSectioner> getNotificationShadeSections() { + if (android.service.notification.Flags.notificationClassification()) { + return List.of( + new NotificationSectioner("PromotionsSection", 0, (record) -> + NotificationChannel.PROMOTIONS_ID.equals(record.getChannel().getId())), + new NotificationSectioner("SocialSection", 0, (record) -> + NotificationChannel.SOCIAL_MEDIA_ID.equals(record.getChannel().getId())), + new NotificationSectioner("NewsSection", 0, (record) -> + NotificationChannel.NEWS_ID.equals(record.getChannel().getId())), + new NotificationSectioner("RecsSection", 0, (record) -> + NotificationChannel.RECS_ID.equals(record.getChannel().getId())), + new NotificationSectioner("AlertingSection", 0, (record) -> + record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT), + new NotificationSectioner("SilentSection", 1, (record) -> + record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT)); + } else { + return List.of( + new NotificationSectioner("AlertingSection", 0, (record) -> + record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT), + new NotificationSectioner("SilentSection", 1, (record) -> + record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT)); + } + } public GroupHelper(Context context, PackageManager packageManager, int autoGroupAtCount, int autoGroupSparseGroupsAtCount, Callback callback) { @@ -131,6 +152,7 @@ public class GroupHelper { mContext = context; mPackageManager = packageManager; mAutogroupSparseGroupsAtCount = autoGroupSparseGroupsAtCount; + NOTIFICATION_SHADE_SECTIONS = getNotificationShadeSections(); } private String generatePackageKey(int userId, String pkg) { diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java index 981891669e7c..abb21323f7f0 100644 --- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java +++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java @@ -489,6 +489,7 @@ public final class NotificationAttentionHelper { } else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) { hasValidSound = false; + hasValidVibrate = false; } } } @@ -753,6 +754,13 @@ public final class NotificationAttentionHelper { // notifying app does not have the VIBRATE permission. final long identity = Binder.clearCallingIdentity(); try { + // Need to explicitly cancel a previously playing vibration + // Otherwise a looping vibration will not be stopped when starting a new one. + if (mVibrateNotificationKey != null + && !mVibrateNotificationKey.equals(record.getKey())) { + mVibrateNotificationKey = null; + mVibratorHelper.cancelVibration(); + } final float scale = getVibrationIntensity(record); final VibrationEffect scaledEffect = Float.compare(scale, DEFAULT_VOLUME) != 0 ? mVibratorHelper.scale(effect, scale) : effect; diff --git a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java index 1938642ef396..e2889fa9cbf6 100644 --- a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java @@ -29,8 +29,8 @@ import android.content.Context; import android.media.AudioAttributes; import android.os.Binder; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.Slog; + import com.android.internal.compat.IPlatformCompat; /** @@ -79,6 +79,11 @@ public class NotificationChannelExtractor implements NotificationSignalExtractor if (restrictAudioAttributesCall() || restrictAudioAttributesAlarm() || restrictAudioAttributesMedia()) { AudioAttributes attributes = record.getChannel().getAudioAttributes(); + if (attributes == null) { + if (DBG) Slog.d(TAG, "missing AudioAttributes"); + return null; + } + boolean updateAttributes = false; if (restrictAudioAttributesCall() && !record.getNotification().isStyle(Notification.CallStyle.class) diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 22b4d5def8f4..5105fd384367 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -1399,7 +1399,29 @@ final class InstallPackageHelper { "Package " + pkgName + " is a persistent app. " + "Persistent apps are not updateable."); } + // When updating an sdk library, make sure that the versionMajor is + // changed if the targetSdkVersion and minSdkVersion have changed + if (parsedPackage.isSdkLibrary() && ps.getPkg() != null + && ps.getPkg().isSdkLibrary()) { + final int oldMinSdk = ps.getPkg().getMinSdkVersion(); + final int newMinSdk = parsedPackage.getMinSdkVersion(); + if (oldTargetSdk != newTargetSdk || oldMinSdk != newMinSdk) { + final int oldVersionMajor = ps.getPkg().getSdkLibVersionMajor(); + final int newVersionMajor = parsedPackage.getSdkLibVersionMajor(); + if (oldVersionMajor == newVersionMajor) { + throw new PrepareFailure( + PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE, + "Failure updating " + pkgName + " as it updates" + + " an sdk library <" + + parsedPackage.getSdkLibraryName() + ">" + + " without changing the versionMajor, but the" + + " targetSdkVersion or minSdkVersion has changed." + ); + } + } + } } + } PackageSetting signatureCheckPs = ps; diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index c95d88e8c697..2c13bd0d91d5 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -165,7 +165,55 @@ "name": "CtsUpdateOwnershipEnforcementTestCases" }, { - "name": "CtsPackageInstallerCUJTestCases", + "name": "CtsPackageInstallerCUJInstallationTestCases", + "file_patterns": [ + "core/java/.*Install.*", + "services/core/.*Install.*", + "services/core/java/com/android/server/pm/.*" + ], + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUninstallationTestCases", + "file_patterns": [ + "core/java/.*Install.*", + "services/core/.*Install.*", + "services/core/java/com/android/server/pm/.*" + ], + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateOwnerShipTestCases", + "file_patterns": [ + "core/java/.*Install.*", + "services/core/.*Install.*", + "services/core/java/com/android/server/pm/.*" + ], + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + } + ] + }, + { + "name": "CtsPackageInstallerCUJUpdateSelfTestCases", "file_patterns": [ "core/java/.*Install.*", "services/core/.*Install.*", diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index aaa38a3a1331..6c78b3c85e18 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -887,7 +887,7 @@ final class DefaultPermissionGrantPolicy { grantPermissionsToSystemPackage(pm, getDefaultSystemHandlerActivityPackage(pm, SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId), - userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS); + userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS); } // Print Spooler diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java index 5a4518606ca6..7ed89728a005 100644 --- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java +++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java @@ -29,8 +29,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.XmlResourceParser; import android.graphics.drawable.Icon; -import android.hardware.input.InputManager; -import android.hardware.input.KeyboardSystemShortcut; +import android.hardware.input.KeyGestureEvent; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; @@ -476,7 +475,7 @@ public class ModifierShortcutManager { + "keyCode=" + KeyEvent.keyCodeToString(keyCode) + "," + " category=" + category + " role=" + role); } - notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(intent)); + notifyKeyGestureCompleted(keyEvent, getKeyGestureTypeFromIntent(intent)); return true; } else { return false; @@ -497,19 +496,19 @@ public class ModifierShortcutManager { + "the activity to which it is registered was not found: " + "META+ or SEARCH" + KeyEvent.keyCodeToString(keyCode)); } - notifyKeyboardShortcutTriggered(keyEvent, getSystemShortcutFromIntent(shortcutIntent)); + notifyKeyGestureCompleted(keyEvent, getKeyGestureTypeFromIntent(shortcutIntent)); return true; } return false; } - private void notifyKeyboardShortcutTriggered(KeyEvent event, - @KeyboardSystemShortcut.SystemShortcut int systemShortcut) { - if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) { + private void notifyKeyGestureCompleted(KeyEvent event, + @KeyGestureEvent.KeyGestureType int gestureType) { + if (gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) { return; } - mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(), - new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut); + mInputManagerInternal.notifyKeyGestureCompleted(event.getDeviceId(), + new int[]{event.getKeyCode()}, event.getMetaState(), gestureType); } /** @@ -710,21 +709,21 @@ public class ModifierShortcutManager { /** - * Find Keyboard shortcut event corresponding to intent filter category. Returns - * {@code SYSTEM_SHORTCUT_UNSPECIFIED if no matching event found} + * Find Key gesture type corresponding to intent filter category. Returns + * {@code KEY_GESTURE_TYPE_UNSPECIFIED if no matching event found} */ - @KeyboardSystemShortcut.SystemShortcut - private static int getSystemShortcutFromIntent(Intent intent) { + @KeyGestureEvent.KeyGestureType + private static int getKeyGestureTypeFromIntent(Intent intent) { Intent selectorIntent = intent.getSelector(); if (selectorIntent != null) { Set<String> selectorCategories = selectorIntent.getCategories(); if (selectorCategories != null && !selectorCategories.isEmpty()) { for (String intentCategory : selectorCategories) { - int systemShortcut = getEventFromSelectorCategory(intentCategory); - if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) { + int keyGestureType = getKeyGestureTypeFromSelectorCategory(intentCategory); + if (keyGestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) { continue; } - return systemShortcut; + return keyGestureType; } } } @@ -733,69 +732,68 @@ public class ModifierShortcutManager { // so check for that. String role = intent.getStringExtra(ModifierShortcutManager.EXTRA_ROLE); if (!TextUtils.isEmpty(role)) { - return getLogEventFromRole(role); + return getKeyGestureTypeFromRole(role); } Set<String> intentCategories = intent.getCategories(); if (intentCategories == null || intentCategories.isEmpty() || !intentCategories.contains(Intent.CATEGORY_LAUNCHER)) { - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED; + return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED; } if (intent.getComponent() == null) { - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED; + return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED; } // TODO(b/280423320): Add new field package name associated in the // KeyboardShortcutEvent atom and log it accordingly. - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_APPLICATION_BY_PACKAGE_NAME; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION_BY_PACKAGE_NAME; } - @KeyboardSystemShortcut.SystemShortcut - private static int getEventFromSelectorCategory(String category) { + @KeyGestureEvent.KeyGestureType + private static int getKeyGestureTypeFromSelectorCategory(String category) { switch (category) { case Intent.CATEGORY_APP_BROWSER: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER; case Intent.CATEGORY_APP_EMAIL: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL; case Intent.CATEGORY_APP_CONTACTS: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS; case Intent.CATEGORY_APP_CALENDAR: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR; case Intent.CATEGORY_APP_CALCULATOR: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR; case Intent.CATEGORY_APP_MUSIC: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC; case Intent.CATEGORY_APP_MAPS: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS; case Intent.CATEGORY_APP_MESSAGING: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING; case Intent.CATEGORY_APP_GALLERY: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_GALLERY; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_GALLERY; case Intent.CATEGORY_APP_FILES: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FILES; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FILES; case Intent.CATEGORY_APP_WEATHER: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_WEATHER; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_WEATHER; case Intent.CATEGORY_APP_FITNESS: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_FITNESS; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_FITNESS; default: - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED; + return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED; } } /** - * Find KeyboardLogEvent corresponding to the provide system role name. - * Returns {@code null} if no matching event found. + * Find KeyGestureType corresponding to the provide system role name. + * Returns {@code KEY_GESTURE_TYPE_UNSPECIFIED} if no matching event found. */ - @KeyboardSystemShortcut.SystemShortcut - private static int getLogEventFromRole(String role) { + @KeyGestureEvent.KeyGestureType + private static int getKeyGestureTypeFromRole(String role) { if (RoleManager.ROLE_BROWSER.equals(role)) { - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER; } else if (RoleManager.ROLE_SMS.equals(role)) { - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING; + return KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING; } else { - Log.w(TAG, "Keyboard shortcut to launch " - + role + " not supported for logging"); - return KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED; + Log.w(TAG, "Keyboard gesture event to launch " + role + " not supported for logging"); + return KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED; } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 720c1c201158..aa56e8d8eb55 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -139,7 +139,7 @@ import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.input.InputManager; -import android.hardware.input.KeyboardSystemShortcut; +import android.hardware.input.KeyGestureEvent; import android.media.AudioManager; import android.media.AudioManagerInternal; import android.media.AudioSystem; @@ -1819,7 +1819,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void handleShortPressOnHome(KeyEvent event) { - notifyKeyboardShortcutTriggered(event, KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME); + notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_HOME); // Turn on the connected TV and switch HDMI input if we're a HDMI playback device. final HdmiControl hdmiControl = getHdmiControl(); @@ -2053,8 +2053,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } switch (mDoubleTapOnHomeBehavior) { case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI: - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH); mHomeConsumed = true; toggleRecentApps(); break; @@ -2082,23 +2082,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { case LONG_PRESS_HOME_ALL_APPS: if (mHasFeatureLeanback) { launchAllAppsAction(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS); } else { launchAllAppsViaA11y(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS); } break; case LONG_PRESS_HOME_ASSIST: - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT); launchAssistAction(null, event.getDeviceId(), event.getEventTime(), AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS); break; case LONG_PRESS_HOME_NOTIFICATION_PANEL: - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL); toggleNotificationPanel(); break; default: @@ -3285,29 +3285,29 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, }; - private void notifyKeyboardShortcutTriggeredOnActionUp(KeyEvent event, - @KeyboardSystemShortcut.SystemShortcut int systemShortcut) { + private void notifyKeyGestureCompletedOnActionUp(KeyEvent event, + @KeyGestureEvent.KeyGestureType int gestureType) { if (event.getAction() != KeyEvent.ACTION_UP) { return; } - notifyKeyboardShortcutTriggered(event, systemShortcut); + notifyKeyGestureCompleted(event, gestureType); } - private void notifyKeyboardShortcutTriggeredOnActionDown(KeyEvent event, - @KeyboardSystemShortcut.SystemShortcut int systemShortcut) { + private void notifyKeyGestureCompletedOnActionDown(KeyEvent event, + @KeyGestureEvent.KeyGestureType int gestureType) { if (event.getAction() != KeyEvent.ACTION_DOWN) { return; } - notifyKeyboardShortcutTriggered(event, systemShortcut); + notifyKeyGestureCompleted(event, gestureType); } - private void notifyKeyboardShortcutTriggered(KeyEvent event, - @KeyboardSystemShortcut.SystemShortcut int systemShortcut) { - if (systemShortcut == KeyboardSystemShortcut.SYSTEM_SHORTCUT_UNSPECIFIED) { + private void notifyKeyGestureCompleted(KeyEvent event, + @KeyGestureEvent.KeyGestureType int gestureType) { + if (gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_UNSPECIFIED) { return; } - mInputManagerInternal.notifyKeyboardShortcutTriggered(event.getDeviceId(), - new int[]{event.getKeyCode()}, event.getMetaState(), systemShortcut); + mInputManagerInternal.notifyKeyGestureCompleted(event.getDeviceId(), + new int[]{event.getKeyCode()}, event.getMetaState(), gestureType); } @Override @@ -3417,8 +3417,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_RECENT_APPS: if (firstDown) { showRecentApps(false /* triggeredFromAltTab */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS); } return true; case KeyEvent.KEYCODE_APP_SWITCH: @@ -3427,8 +3427,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { preloadRecentApps(); } else if (!down) { toggleRecentApps(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH); } } return true; @@ -3437,8 +3437,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, deviceId, event.getEventTime(), AssistUtils.INVOCATION_TYPE_UNKNOWN); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT); return true; } break; @@ -3451,16 +3451,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_I: if (firstDown && event.isMetaPressed()) { showSystemSettings(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS); return true; } break; case KeyEvent.KEYCODE_L: if (firstDown && event.isMetaPressed()) { lockNow(null /* options */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN); return true; } break; @@ -3468,12 +3468,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (firstDown && event.isMetaPressed()) { if (event.isCtrlPressed()) { sendSystemKeyToStatusBarAsync(event); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES); } else { toggleNotificationPanel(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL); } return true; } @@ -3481,8 +3481,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_S: if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) { interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT); return true; } break; @@ -3495,16 +3495,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (RemoteException e) { Slog.d(TAG, "Error taking bugreport", e); } - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT); return true; } } // fall through case KeyEvent.KEYCODE_ESCAPE: if (firstDown && event.isMetaPressed()) { - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK); injectBackGesture(event.getDownTime()); return true; } @@ -3513,8 +3513,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); if (statusbar != null) { statusbar.moveFocusedTaskToFullscreen(getTargetDisplayIdForKeyEvent(event)); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION); return true; } } @@ -3524,8 +3524,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); if (statusbar != null) { statusbar.moveFocusedTaskToDesktop(getTargetDisplayIdForKeyEvent(event)); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE); return true; } } @@ -3535,15 +3535,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (event.isCtrlPressed()) { moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event), true /* leftOrTop */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION); } else if (event.isAltPressed()) { setSplitscreenFocus(true /* leftOrTop */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS); } else { - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK); injectBackGesture(event.getDownTime()); } return true; @@ -3554,13 +3554,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (event.isCtrlPressed()) { moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event), false /* leftOrTop */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION); return true; } else if (event.isAltPressed()) { setSplitscreenFocus(false /* leftOrTop */); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_CHANGE_SPLITSCREEN_FOCUS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS); return true; } } @@ -3568,8 +3568,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_SLASH: if (firstDown && event.isMetaPressed() && !keyguardOn) { toggleKeyboardShortcutsMenu(event.getDeviceId()); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER); return true; } break; @@ -3622,31 +3622,31 @@ public class PhoneWindowManager implements WindowManagerPolicy { intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true); startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); - int systemShortcut = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN - ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN - : KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP; - notifyKeyboardShortcutTriggered(event, systemShortcut); + int gestureType = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN + ? KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN + : KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP; + notifyKeyGestureCompleted(event, gestureType); } return true; case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN: if (down) { mInputManagerInternal.decrementKeyboardBacklight(event.getDeviceId()); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN); } return true; case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP: if (down) { mInputManagerInternal.incrementKeyboardBacklight(event.getDeviceId()); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP); } return true; case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE: // TODO: Add logic if (!down) { - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE); } return true; case KeyEvent.KEYCODE_VOLUME_UP: @@ -3673,8 +3673,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (firstDown && !keyguardOn && isUserSetupComplete()) { if (event.isMetaPressed()) { showRecentApps(false); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS); return true; } else if (mRecentAppsHeldModifiers == 0) { final int shiftlessModifiers = @@ -3683,8 +3683,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { shiftlessModifiers, KeyEvent.META_ALT_ON)) { mRecentAppsHeldModifiers = shiftlessModifiers; showRecentApps(true); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS); return true; } } @@ -3697,20 +3697,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS); msg.setAsynchronous(true); msg.sendToTarget(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ALL_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS); } else { launchAllAppsViaA11y(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS); } } return true; case KeyEvent.KEYCODE_NOTIFICATION: if (!down) { toggleNotificationPanel(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL); } return true; case KeyEvent.KEYCODE_SEARCH: @@ -3718,8 +3718,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { switch (mSearchKeyBehavior) { case SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY: { launchTargetSearchActivity(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH); return true; } case SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH: @@ -3732,8 +3732,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (firstDown) { int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; sendSwitchKeyboardLayout(event, focusedToken, direction); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH); return true; } break; @@ -3752,13 +3752,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPendingCapsLockToggle) { mInputManagerInternal.toggleCapsLock(event.getDeviceId()); mPendingCapsLockToggle = false; - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK); } else if (mPendingMetaAction) { if (!canceled) { launchAllAppsViaA11y(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS); } mPendingMetaAction = false; } @@ -3786,16 +3786,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPendingCapsLockToggle) { mInputManagerInternal.toggleCapsLock(event.getDeviceId()); mPendingCapsLockToggle = false; - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK); return true; } } break; case KeyEvent.KEYCODE_CAPS_LOCK: if (!down) { - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK); } break; case KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY: @@ -3809,12 +3809,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (firstDown) { if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL) { toggleNotificationPanel(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL); } else if (mSettingsKeyBehavior == SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY) { showSystemSettings(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS); } } return true; @@ -4760,8 +4760,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Handle special keys. switch (keyCode) { case KeyEvent.KEYCODE_BACK: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK); if (down) { // There may have other embedded activities on the same Task. Try to move the // focus before processing the back event. @@ -4782,12 +4782,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: { - int systemShortcut = keyCode == KEYCODE_VOLUME_DOWN - ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN + int gestureType = keyCode == KEYCODE_VOLUME_DOWN + ? KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN : keyCode == KEYCODE_VOLUME_UP - ? KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP - : KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE; - notifyKeyboardShortcutTriggeredOnActionDown(event, systemShortcut); + ? KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP + : KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE; + notifyKeyGestureCompletedOnActionDown(event, gestureType); if (down) { sendSystemKeyToStatusBarAsync(event); @@ -4888,8 +4888,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } case KeyEvent.KEYCODE_TV_POWER: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER); result &= ~ACTION_PASS_TO_USER; isWakeKey = false; // wake-up will be handled separately if (down && hdmiControlManager != null) { @@ -4899,8 +4899,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } case KeyEvent.KEYCODE_POWER: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER); EventLogTags.writeInterceptPower( KeyEvent.actionToString(event.getAction()), mPowerKeyHandled ? 1 : 0, @@ -4923,16 +4923,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: // fall through case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION); result &= ~ACTION_PASS_TO_USER; interceptSystemNavigationKey(event); break; } case KeyEvent.KEYCODE_SLEEP: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP); result &= ~ACTION_PASS_TO_USER; isWakeKey = false; if (!mPowerManager.isInteractive()) { @@ -4948,8 +4948,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } case KeyEvent.KEYCODE_SOFT_SLEEP: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP); result &= ~ACTION_PASS_TO_USER; isWakeKey = false; if (!down) { @@ -4960,8 +4960,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } case KeyEvent.KEYCODE_WAKEUP: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP); result &= ~ACTION_PASS_TO_USER; isWakeKey = true; break; @@ -4970,8 +4970,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_MUTE: result &= ~ACTION_PASS_TO_USER; if (down && event.getRepeatCount() == 0) { - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE); toggleMicrophoneMuteFromKey(); } break; @@ -4986,8 +4986,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { - notifyKeyboardShortcutTriggeredOnActionUp(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY); + notifyKeyGestureCompletedOnActionUp(event, + KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY); if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { // If the global session is active pass all media keys to it // instead of the active window. @@ -5032,8 +5032,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { 0 /* unused */, event.getEventTime() /* eventTime */); msg.setAsynchronous(true); msg.sendToTarget(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT); } result &= ~ACTION_PASS_TO_USER; break; @@ -5044,8 +5044,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK); msg.setAsynchronous(true); msg.sendToTarget(); - notifyKeyboardShortcutTriggered(event, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT); } result &= ~ACTION_PASS_TO_USER; break; diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 72594b3a73c5..2e8a0c678f48 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -433,7 +433,8 @@ public class PowerGroup { boolean updateLocked(float screenBrightnessOverride, CharSequence overrideTag, boolean useProximitySensor, boolean boostScreenBrightness, int dozeScreenState, @Display.StateReason int dozeScreenStateReason, - float dozeScreenBrightness, boolean overrideDrawWakeLock, + float dozeScreenBrightness, boolean useNormalBrightnessForDoze, + boolean overrideDrawWakeLock, PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean waitForNegativeProximity, @@ -461,11 +462,13 @@ public class PowerGroup { } } mDisplayPowerRequest.dozeScreenBrightness = dozeScreenBrightness; + mDisplayPowerRequest.useNormalBrightnessForDoze = useNormalBrightnessForDoze; } else { mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN; mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; mDisplayPowerRequest.dozeScreenStateReason = Display.STATE_REASON_DEFAULT_POLICY; + mDisplayPowerRequest.useNormalBrightnessForDoze = false; } mDisplayPowerRequest.lowPowerMode = powerSaverState.batterySaverEnabled; mDisplayPowerRequest.screenLowPowerBrightnessFactor = powerSaverState.brightnessFactor; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 699c9b567498..27024a7e7997 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -101,7 +101,6 @@ import android.provider.DeviceConfigInterface; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.service.dreams.DreamManagerInternal; -import android.sysprop.InitProperties; import android.sysprop.PowerProperties; import android.util.ArrayMap; import android.util.IntArray; @@ -132,7 +131,6 @@ import com.android.server.RescueParty; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.UiThread; -import com.android.server.UserspaceRebootLogger; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.display.feature.DeviceConfigParameterProvider; @@ -662,6 +660,7 @@ public final class PowerManagerService extends SystemService */ private float mDozeScreenBrightnessOverrideFromDreamManagerFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; + private boolean mUseNormalBrightnessForDoze; // Keep display state when dozing. private boolean mDrawWakeLockOverrideFromSidekick; @@ -1273,8 +1272,7 @@ public final class PowerManagerService extends SystemService mHalInteractiveModeEnabled = true; mWakefulnessRaw = WAKEFULNESS_AWAKE; - sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1") - || InitProperties.userspace_reboot_in_progress().orElse(false); + sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1"); mNativeWrapper.nativeInit(this); mNativeWrapper.nativeSetAutoSuspend(false); @@ -3656,6 +3654,7 @@ public final class PowerManagerService extends SystemService mDozeScreenStateOverrideFromDreamManager, mDozeScreenStateOverrideReasonFromDreamManager, mDozeScreenBrightnessOverrideFromDreamManagerFloat, + mUseNormalBrightnessForDoze, mDrawWakeLockOverrideFromSidekick, mBatterySaverSupported ? @@ -4030,7 +4029,6 @@ public final class PowerManagerService extends SystemService throw new UnsupportedOperationException( "Attempted userspace reboot on a device that doesn't support it"); } - UserspaceRebootLogger.noteUserspaceRebootWasRequested(); } if (mHandler == null || !mSystemReady) { if (RescueParty.isRecoveryTriggeredReboot()) { @@ -4470,13 +4468,13 @@ public final class PowerManagerService extends SystemService private void setDozeOverrideFromDreamManagerInternal( int screenState, @Display.StateReason int reason, float screenBrightnessFloat, - int screenBrightnessInt) { + int screenBrightnessInt, boolean useNormalBrightnessForDoze) { synchronized (mLock) { if (mDozeScreenStateOverrideFromDreamManager != screenState || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightnessInt || !BrightnessSynchronizer.floatEquals( - mDozeScreenBrightnessOverrideFromDreamManagerFloat, - screenBrightnessFloat)) { + mDozeScreenBrightnessOverrideFromDreamManagerFloat, screenBrightnessFloat) + || mUseNormalBrightnessForDoze != useNormalBrightnessForDoze) { mDozeScreenStateOverrideFromDreamManager = screenState; mDozeScreenStateOverrideReasonFromDreamManager = reason; mDozeScreenBrightnessOverrideFromDreamManager = screenBrightnessInt; @@ -4484,6 +4482,7 @@ public final class PowerManagerService extends SystemService isValidBrightnessValue(screenBrightnessFloat) ? screenBrightnessFloat : BrightnessSynchronizer.brightnessIntToFloat(screenBrightnessInt); + mUseNormalBrightnessForDoze = useNormalBrightnessForDoze; mDirty |= DIRTY_SETTINGS; updatePowerStateLocked(); } @@ -4798,6 +4797,7 @@ public final class PowerManagerService extends SystemService pw.println(" mDrawWakeLockOverrideFromSidekick=" + mDrawWakeLockOverrideFromSidekick); pw.println(" mDozeScreenBrightnessOverrideFromDreamManager=" + mDozeScreenBrightnessOverrideFromDreamManager); + pw.println(" mUseNormalBrightnessForDoze=" + mUseNormalBrightnessForDoze); pw.println(" mScreenBrightnessMinimum=" + mScreenBrightnessMinimum); pw.println(" mScreenBrightnessMaximum=" + mScreenBrightnessMaximum); pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault); @@ -7115,7 +7115,8 @@ public final class PowerManagerService extends SystemService @Override public void setDozeOverrideFromDreamManager( - int screenState, int reason, float screenBrightnessFloat, int screenBrightnessInt) { + int screenState, int reason, float screenBrightnessFloat, int screenBrightnessInt, + boolean useNormalBrightnessForDoze) { switch (screenState) { case Display.STATE_UNKNOWN: case Display.STATE_OFF: @@ -7138,7 +7139,7 @@ public final class PowerManagerService extends SystemService screenBrightnessFloat = PowerManager.BRIGHTNESS_INVALID_FLOAT; } setDozeOverrideFromDreamManagerInternal(screenState, reason, screenBrightnessFloat, - screenBrightnessInt); + screenBrightnessInt, useNormalBrightnessForDoze); } @Override diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java index 68eb8eb1deaf..480db25ec606 100644 --- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java +++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java @@ -76,8 +76,6 @@ public class TracingServiceProxy extends SystemService { // Keep this in sync with the definitions in TraceService private static final String INTENT_ACTION_NOTIFY_SESSION_STOPPED = "com.android.traceur.NOTIFY_SESSION_STOPPED"; - private static final String INTENT_ACTION_NOTIFY_SESSION_STOLEN = - "com.android.traceur.NOTIFY_SESSION_STOLEN"; private static final int REPORT_BEGIN = TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN; @@ -97,13 +95,12 @@ public class TracingServiceProxy extends SystemService { private final ITracingServiceProxy.Stub mTracingServiceProxy = new ITracingServiceProxy.Stub() { /** - * Notifies system tracing app that a tracing session has ended. If a session is repurposed - * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but - * there is no buffer available to dump. + * Notifies system tracing app that a tracing session has ended. sessionStolen is ignored, + * as trace sessions are no longer stolen and are always cloned instead. */ @Override - public void notifyTraceSessionEnded(boolean sessionStolen) { - TracingServiceProxy.this.notifyTraceur(sessionStolen); + public void notifyTraceSessionEnded(boolean sessionStolen /* unused */) { + TracingServiceProxy.this.notifyTraceur(); } @Override @@ -132,7 +129,7 @@ public class TracingServiceProxy extends SystemService { } } - private void notifyTraceur(boolean sessionStolen) { + private void notifyTraceur() { final Intent intent = new Intent(); try { @@ -141,11 +138,7 @@ public class TracingServiceProxy extends SystemService { PackageManager.MATCH_SYSTEM_ONLY); intent.setClassName(info.packageName, TRACING_APP_ACTIVITY); - if (sessionStolen) { - intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOLEN); - } else { - intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOPPED); - } + intent.setAction(INTENT_ACTION_NOTIFY_SESSION_STOPPED); final long identity = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java index eccbffb53529..07610872b208 100644 --- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java +++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java @@ -364,10 +364,7 @@ public final class HapticFeedbackVibrationProvider { if ((privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) == 0) { return TOUCH_VIBRATION_ATTRIBUTES; } - return new VibrationAttributes.Builder(IME_FEEDBACK_VIBRATION_ATTRIBUTES) - // TODO(b/332661766): Remove CATEGORY_KEYBOARD logic - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) - .build(); + return IME_FEEDBACK_VIBRATION_ATTRIBUTES; } @Nullable diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index 5c567da7844f..aa4b9f3e9d7d 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -282,12 +282,6 @@ abstract class Vibration { VibrationScaler.scaleLevelToString(mScaleLevel), mAdaptiveScale, Long.toBinaryString(mCallerInfo.attrs.getFlags()), mCallerInfo.attrs.usageToString()); - // Optional, most vibrations have category unknown so skip them to simplify the logs - String categoryStr = - mCallerInfo.attrs.getCategory() != VibrationAttributes.CATEGORY_UNKNOWN - ? " | category=" + VibrationAttributes.categoryToString( - mCallerInfo.attrs.getCategory()) - : ""; // Optional, most vibrations should not be defined via AudioAttributes // so skip them to simplify the logs String audioUsageStr = @@ -302,7 +296,7 @@ abstract class Vibration { " | played: %s | original: %s", mPlayedEffect == null ? null : mPlayedEffect.toDebugString(), mOriginalEffect == null ? null : mOriginalEffect.toDebugString()); - pw.println(timingsStr + paramStr + categoryStr + audioUsageStr + callerStr + effectStr); + pw.println(timingsStr + paramStr + audioUsageStr + callerStr + effectStr); } /** Write this info into given {@link PrintWriter}. */ @@ -335,7 +329,6 @@ abstract class Vibration { final VibrationAttributes attrs = mCallerInfo.attrs; proto.write(VibrationAttributesProto.USAGE, attrs.getUsage()); proto.write(VibrationAttributesProto.AUDIO_USAGE, attrs.getAudioUsage()); - proto.write(VibrationAttributesProto.CATEGORY, attrs.getCategory()); proto.write(VibrationAttributesProto.FLAGS, attrs.getFlags()); proto.end(attrsToken); diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java index a74c4e07c9ed..b3862cc51c07 100644 --- a/services/core/java/com/android/server/vibrator/VibrationScaler.java +++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java @@ -134,7 +134,8 @@ final class VibrationScaler { return effect.resolve(mDefaultVibrationAmplitude) .applyEffectStrength(newEffectStrength) .scale(scaleFactor) - .scaleLinearly(adaptiveScale); + // Make sure this is the last one so it is applied on top of the settings scaling. + .applyAdaptiveScale(adaptiveScale); } /** diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index 8cc157c2ed81..4fc0b74ecb80 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -279,8 +279,8 @@ final class VibratorController { vendorEffect.getVendorData().writeToParcel(vendorData, /* flags= */ 0); vendorData.setDataPosition(0); long duration = mNativeWrapper.performVendorEffect(vendorData, - vendorEffect.getEffectStrength(), vendorEffect.getLinearScale(), - vibrationId); + vendorEffect.getEffectStrength(), vendorEffect.getScale(), + vendorEffect.getAdaptiveScale(), vibrationId); if (duration > 0) { mCurrentAmplitude = -1; notifyListenerOnVibrating(true); @@ -459,7 +459,7 @@ final class VibratorController { long vibrationId); private static native long performVendorEffect(long nativePtr, Parcel vendorData, - long strength, float scale, long vibrationId); + long strength, float scale, float adaptiveScale, long vibrationId); private static native long performComposedEffect(long nativePtr, PrimitiveSegment[] effect, long vibrationId); @@ -518,8 +518,9 @@ final class VibratorController { /** Turns vibrator on to perform a vendor-specific effect. */ public long performVendorEffect(Parcel vendorData, long strength, float scale, - long vibrationId) { - return performVendorEffect(mNativePtr, vendorData, strength, scale, vibrationId); + float adaptiveScale, long vibrationId) { + return performVendorEffect(mNativePtr, vendorData, strength, scale, adaptiveScale, + vibrationId); } /** Turns vibrator on to perform effect composed of give primitives effect. */ diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index f2ad5b95fe5e..dd16d2433a64 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -487,25 +487,37 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { HalVibration performHapticFeedbackInternal( int uid, int deviceId, String opPkg, int constant, String reason, IBinder token, int flags, int privFlags) { + + // Make sure we report the constant id in the requested haptic feedback reason. + reason = "performHapticFeedback(constant=" + constant + "): " + reason; + HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider(); if (hapticVibrationProvider == null) { Slog.e(TAG, "performHapticFeedback; haptic vibration provider not ready."); + logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason, + Vibration.Status.IGNORED_ERROR_SCHEDULING); return null; } + if (hapticVibrationProvider.isRestrictedHapticFeedback(constant) && !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) { Slog.w(TAG, "performHapticFeedback; no permission for system constant " + constant); + logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason, + Vibration.Status.IGNORED_MISSING_PERMISSION); return null; } + VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant); if (effect == null) { Slog.w(TAG, "performHapticFeedback; vibration absent for constant " + constant); + logAndRecordPerformHapticFeedbackAttempt(uid, deviceId, opPkg, reason, + Vibration.Status.IGNORED_UNSUPPORTED); return null; } + CombinedVibration vib = CombinedVibration.createParallel(effect); VibrationAttributes attrs = hapticVibrationProvider.getVibrationAttributesForHapticFeedback( constant, flags, privFlags); - reason = "performHapticFeedback(constant=" + constant + "): " + reason; VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant); return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, vib, attrs, reason, token); } @@ -563,22 +575,27 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private HalVibration vibrateInternal(int uid, int deviceId, String opPkg, @NonNull CombinedVibration effect, @NonNull VibrationAttributes attrs, String reason, IBinder token) { + Vibration.CallerInfo callerInfo = + new Vibration.CallerInfo(attrs, uid, deviceId, opPkg, reason); if (token == null) { Slog.e(TAG, "token must not be null"); + logAndRecordVibrationAttempt(effect, callerInfo, Vibration.Status.IGNORED_ERROR_TOKEN); return null; } if (effect.hasVendorEffects() && !hasPermission(android.Manifest.permission.VIBRATE_VENDOR_EFFECTS)) { - Slog.w(TAG, "vibrate; no permission for vendor effects"); + Slog.e(TAG, "vibrate; no permission for vendor effects"); + logAndRecordVibrationAttempt(effect, callerInfo, + Vibration.Status.IGNORED_MISSING_PERMISSION); return null; } enforceUpdateAppOpsStatsPermission(uid); if (!isEffectValid(effect)) { + logAndRecordVibrationAttempt(effect, callerInfo, Vibration.Status.IGNORED_UNSUPPORTED); return null; } // Create Vibration.Stats as close to the received request as possible, for tracking. - HalVibration vib = new HalVibration(token, effect, - new Vibration.CallerInfo(attrs, uid, deviceId, opPkg, reason)); + HalVibration vib = new HalVibration(token, effect, callerInfo); fillVibrationFallbacks(vib, effect); if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) { @@ -973,6 +990,22 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES); } + private void logAndRecordPerformHapticFeedbackAttempt(int uid, int deviceId, String opPkg, + String reason, Vibration.Status status) { + Vibration.CallerInfo callerInfo = new Vibration.CallerInfo( + VibrationAttributes.createForUsage(VibrationAttributes.USAGE_UNKNOWN), + uid, deviceId, opPkg, reason); + logAndRecordVibrationAttempt(/* effect= */ null, callerInfo, status); + } + + private void logAndRecordVibrationAttempt(@Nullable CombinedVibration effect, + Vibration.CallerInfo callerInfo, Vibration.Status status) { + logAndRecordVibration( + new Vibration.DebugInfo(status, new VibrationStats(), + effect, /* originalEffect= */ null, VibrationScaler.SCALE_NONE, + VibrationScaler.ADAPTIVE_SCALE_NONE, callerInfo)); + } + private void logAndRecordVibration(Vibration.DebugInfo info) { info.logMetrics(mFrameworkStatsLogger); logVibrationStatus(info.mCallerInfo.uid, info.mCallerInfo.attrs, info.mStatus); diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 2c734127b7ea..10ce8c273736 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -1617,8 +1617,7 @@ final class AccessibilityController { // causing the notifying, or the recents/home window is removed, then we won't need the // delayed notification anymore. void onWMTransition(@TransitionType int type, @TransitionFlags int flags) { - if (Flags.delayNotificationToMagnificationWhenRecentsWindowToFrontTransition() - && type == WindowManager.TRANSIT_TO_FRONT + if (type == WindowManager.TRANSIT_TO_FRONT && (flags & TRANSIT_FLAG_IS_RECENTS) != 0) { // Delay the recents to front transition notification then send after if needed. mHasDelayedNotificationForRecentsToFrontTransition = true; @@ -2451,7 +2450,7 @@ final class AccessibilityController { long tokenInner = os.start(WINDOW_MANAGER_SERVICE); synchronized (mService.mGlobalLock) { - mService.dumpDebugLocked(os, WindowTraceLogLevel.ALL); + mService.dumpDebugLocked(os, WindowTracingLogLevel.ALL); } os.end(tokenInner); os.write(CPU_STATS, printCpuStats(reportedTimeStampNanos)); diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 0c10551a9b23..e27b2beb3d5a 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -1156,7 +1156,7 @@ class ActivityClientController extends IActivityClientController.Stub { } if (rootTask.inFreeformWindowingMode()) { - rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FULLSCREEN); rootTask.setBounds(null); } else if (!r.supportsFreeform()) { throw new IllegalStateException( @@ -1165,9 +1165,9 @@ class ActivityClientController extends IActivityClientController.Stub { // If the window is on a freeform display, set it to undefined. It will be // resolved to freeform and it can adjust windowing mode when the display mode // changes in runtime. - rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); } else { - rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FREEFORM); } } } finally { @@ -1278,7 +1278,7 @@ class ActivityClientController extends IActivityClientController.Stub { if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) { final int restoreWindowingMode = requester.getRequestedOverrideWindowingMode(); targetWindowingMode = WINDOWING_MODE_FULLSCREEN; - requester.setWindowingMode(targetWindowingMode); + requester.setRootTaskWindowingMode(targetWindowingMode); // The restore windowing mode must be set after the windowing mode is set since // Task#setWindowingMode resets the restore windowing mode to WINDOWING_MODE_INVALID. requester.mMultiWindowRestoreWindowingMode = restoreWindowingMode; @@ -1297,9 +1297,8 @@ class ActivityClientController extends IActivityClientController.Stub { public void startLockTaskModeByToken(IBinder token) { synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r != null) { - mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); - } + if (r == null) return; + mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index a76f1b62fe02..0bd844192233 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -789,8 +789,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private boolean mWillCloseOrEnterPip; - final LetterboxUiController mLetterboxUiController; - /** * App Compat Facade */ @@ -1324,7 +1322,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(prefix); pw.println("mWaitForEnteringPinnedMode=true"); } - mLetterboxUiController.dump(pw, prefix); + mAppCompatController.dump(pw, prefix); } static boolean dumpActivity(FileDescriptor fd, PrintWriter pw, int index, ActivityRecord r, @@ -1988,12 +1986,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Don't move below setActivityType since it triggers onConfigurationChange -> - // resolveOverrideConfiguration that requires having mLetterboxUiController initialised. + // resolveOverrideConfiguration that requires having mAppCompatController initialised. // Don't move below setOrientation(info.screenOrientation) since it triggers - // getOverrideOrientation that requires having mLetterboxUiController - // initialised. + // getOverrideOrientation that requires having mAppCompatController initialised. mAppCompatController = new AppCompatController(mWmService, this); - mLetterboxUiController = new LetterboxUiController(mWmService, this); mResolveConfigHint = new TaskFragment.ConfigOverrideHint(); if (mWmService.mFlags.mInsetsDecoupledConfiguration) { // When the stable configuration is the default behavior, override for the legacy apps @@ -2016,7 +2012,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mIsUserAlwaysVisible = properties != null && properties.getAlwaysVisible(); mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || mIsUserAlwaysVisible; - setOrientation(info.screenOrientation); + setOverrideOrientation(info.screenOrientation); mRotationAnimationHint = info.rotationAnimation; mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0; @@ -3626,10 +3622,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final WindowContainer<?> trigger = endTask ? task : this; final Transition newTransition = mTransitionController.requestCloseTransitionIfNeeded(trigger); - if (newTransition != null) { - newTransition.collectClose(trigger); - } else if (mTransitionController.isCollecting()) { - mTransitionController.getCollectingTransition().collectClose(trigger); + final Transition transition = newTransition != null + ? newTransition : mTransitionController.getCollectingTransition(); + if (transition != null) { + transition.collectClose(trigger); } if (isState(RESUMED)) { if (endTask) { @@ -4302,9 +4298,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // closing the task. final WindowContainer trigger = remove && task != null && task.getChildCount() == 1 ? task : this; - final Transition newTransit = mTransitionController.requestCloseTransitionIfNeeded(trigger); - if (newTransit != null) { - newTransit.collectClose(trigger); + final Transition tr = mTransitionController.requestCloseTransitionIfNeeded(trigger); + if (tr != null) { + tr.collectClose(trigger); } else if (mTransitionController.isCollecting()) { mTransitionController.getCollectingTransition().collectClose(trigger); } @@ -5320,12 +5316,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A task.lastDescription = description; } - void setDeferHidingClient(boolean deferHidingClient) { - if (mDeferHidingClient == deferHidingClient) { - return; - } - mDeferHidingClient = deferHidingClient; - if (!mDeferHidingClient && !mVisibleRequested) { + void setDeferHidingClient() { + mDeferHidingClient = true; + } + + void clearDeferHidingClient() { + if (!mDeferHidingClient) return; + mDeferHidingClient = false; + if (!mVisibleRequested) { // Hiding the client is no longer deferred and the app isn't visible still, go ahead and // update the visibility. setVisibility(false); @@ -5449,8 +5447,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean isCollecting = false; boolean inFinishingTransition = false; if (mTransitionController.isShellTransitionsEnabled()) { - isCollecting = mTransitionController.isCollecting(); - if (isCollecting) { + if (mTransitionController.isCollecting()) { + isCollecting = true; mTransitionController.collect(this); } else { // Failsafe to make sure that we show any activities that were incorrectly hidden @@ -6195,7 +6193,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // stopped or stopping. This gives it a chance to enter Pip in onPause(). final boolean deferHidingClient = canEnterPictureInPicture && !isState(STARTED, STOPPING, STOPPED, PAUSED); - setDeferHidingClient(deferHidingClient); + if (deferHidingClient) { + setDeferHidingClient(); + } else { + clearDeferHidingClient(); + } setVisibility(false); switch (getState()) { @@ -6234,7 +6236,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Slog.v(TAG_VISIBILITY, "Resume visible activity, " + this); } return getRootTask().resumeTopActivityUncheckedLocked(activeActivity /* prev */, - null /* options */); + null /* options */, false /* skipPause */); } else if (shouldPauseActivity(activeActivity)) { if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this); @@ -6524,9 +6526,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void stopIfPossible() { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this); if (finishing) { - Slog.e(TAG, "Request to stop a finishing activity: " + this); - destroyIfPossible("stopIfPossible-finishing"); - return; + throw new IllegalStateException("Request to stop a finishing activity: " + this); } if (isNoHistory()) { if (!task.shouldSleepActivities()) { @@ -7538,6 +7538,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mStartingWindow == win) { // This could only happen when the window is removed from hierarchy. So do not keep its // reference anymore. + if (mStartingSurface != null) { + // Ensure the reference in client side can be removed. + mStartingSurface.remove(false /* animate */, false /* hasImeSurface */); + } mStartingWindow = null; mStartingData = null; mStartingSurface = null; @@ -10328,7 +10332,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Write all fields to an {@code ActivityRecordProto}. This assumes the * {@code ActivityRecordProto} is the outer-most proto data. */ - void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) { + void dumpDebug(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) { writeNameToProto(proto, NAME); super.dumpDebug(proto, WINDOW_TOKEN, logLevel); proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing); @@ -10406,9 +10410,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { // Critical log level logs only visible elements to mitigate performance overheard - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index a0ef03095010..1660ca913e59 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -612,11 +612,10 @@ public class ActivityStartController { final Task task = r.getTask(); mService.deferWindowLayout(); try { - final TransitionController controller = r.mTransitionController; - final Transition transition = controller.getCollectingTransition(); + final Transition transition = r.mTransitionController.getCollectingTransition(); if (transition != null) { transition.setRemoteAnimationApp(r.app.getThread()); - controller.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask)); + transition.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask)); } task.moveToFront("startExistingRecents"); task.mInResumeTopActivity = true; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 18aa9a026675..64791112a129 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1355,9 +1355,21 @@ class ActivityStarter { mService.resumeAppSwitches(); } + // Only do the create here since startActivityInner can abort. If it doesn't abort, + // the requestStart will be sent in handleStartRequest. + final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled() + ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null; + // Because startActivity must run immediately, it can get combined with another + // transition meaning it is no-longer independent. This is NOT desirable, but is the + // only option for the time being. + final boolean isIndependent = newTransition != null; + final Transition transition = isIndependent ? newTransition + : mService.getTransitionController().getCollectingTransition(); + mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, checkedOptions, - inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid); + inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid, transition, + isIndependent); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; @@ -1509,33 +1521,27 @@ class ActivityStarter { int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, BalVerdict balVerdict, - NeededUriGrants intentGrants, int realCallingUid) { + NeededUriGrants intentGrants, int realCallingUid, Transition transition, + boolean isIndependentLaunch) { int result = START_CANCELED; final Task startedActivityRootTask; - // Create a transition now to record the original intent of actions taken within - // startActivityInner. Otherwise, logic in startActivityInner could start a different - // transition based on a sub-action. - // Only do the create here (and defer requestStart) since startActivityInner might abort. - final TransitionController transitionController = r.mTransitionController; - Transition newTransition = transitionController.isShellTransitionsEnabled() - ? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null; RemoteTransition remoteTransition = r.takeRemoteTransition(); // Create a display snapshot as soon as possible. - if (newTransition != null && mRequest.freezeScreen) { + if (isIndependentLaunch && mRequest.freezeScreen) { final TaskDisplayArea tda = mLaunchParams.hasPreferredTaskDisplayArea() ? mLaunchParams.mPreferredTaskDisplayArea : mRootWindowContainer.getDefaultTaskDisplayArea(); final DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate( tda.getDisplayId()); if (dc != null) { - transitionController.collect(dc); - transitionController.collectVisibleChange(dc); + transition.collect(dc); + transition.collectVisibleChange(dc); } } try { mService.deferWindowLayout(); - transitionController.collect(r); + r.mTransitionController.collect(r); try { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, @@ -1545,8 +1551,8 @@ class ActivityStarter { Slog.e(TAG, "Exception on startActivityInner", ex); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); - startedActivityRootTask = handleStartResult(r, options, result, newTransition, - remoteTransition); + startedActivityRootTask = handleStartResult(r, options, result, isIndependentLaunch, + remoteTransition, transition); } } finally { mService.continueWindowLayout(); @@ -1571,8 +1577,8 @@ class ActivityStarter { * @return the root task where the successful started activity resides. */ private @Nullable Task handleStartResult(@NonNull ActivityRecord started, - ActivityOptions options, int result, Transition newTransition, - RemoteTransition remoteTransition) { + ActivityOptions options, int result, boolean isIndependentLaunch, + RemoteTransition remoteTransition, @NonNull Transition transition) { final boolean userLeaving = mSupervisor.mUserLeaving; mSupervisor.mUserLeaving = false; final Task currentRootTask = started.getRootTask(); @@ -1596,8 +1602,9 @@ class ActivityStarter { && !startedActivityRootTask.mCreatedByOrganizer) { startedActivityRootTask.removeIfPossible("handleStartResult"); } - if (newTransition != null) { - newTransition.abort(); + if (isIndependentLaunch + && mService.getTransitionController().isShellTransitionsEnabled()) { + transition.abort(); } return null; } @@ -1649,44 +1656,46 @@ class ActivityStarter { // The activity is started new rather than just brought forward, so record it as an // existence change. transitionController.collectExistenceChange(started); - } else if (result == START_DELIVERED_TO_TOP && newTransition != null + } else if (result == START_DELIVERED_TO_TOP && isIndependentLaunch // An activity has changed order/visibility or the task is occluded by a transient // activity, so this isn't just deliver-to-top && mMovedToTopActivity == null && !transitionController.hasOrderChanges() && !transitionController.isTransientHide(startedActivityRootTask) - && !newTransition.hasChanged(mLastStartActivityRecord)) { + && !transition.hasChanged(mLastStartActivityRecord)) { // We just delivered to top, so there isn't an actual transition here. if (!forceTransientTransition) { - newTransition.abort(); - newTransition = null; + transition.abort(); + transition = null; } } - if (forceTransientTransition) { - transitionController.collect(mLastStartActivityRecord); - transitionController.collect(mPriorAboveTask); + if (forceTransientTransition && transition != null) { + transition.collect(mLastStartActivityRecord); + transition.collect(mPriorAboveTask); // If keyguard is active and occluded, the transient target won't be moved to front // to be collected, so set transient again after it is collected. - transitionController.setTransientLaunch(mLastStartActivityRecord, mPriorAboveTask); + transition.setTransientLaunch(mLastStartActivityRecord, mPriorAboveTask); final DisplayContent dc = mLastStartActivityRecord.getDisplayContent(); // update wallpaper target to TransientHide dc.mWallpaperController.adjustWallpaperWindows(); // execute transition because there is no change - transitionController.setReady(dc, true /* ready */); + transition.setReady(dc, true /* ready */); } - if (!userLeaving) { + if (!userLeaving && transition != null) { // no-user-leaving implies not entering PiP. - transitionController.setCanPipOnFinish(false /* canPipOnFinish */); + transition.setCanPipOnFinish(false /* canPipOnFinish */); } - if (newTransition != null) { - transitionController.requestStartTransition(newTransition, + if (isIndependentLaunch && transition != null) { + transitionController.requestStartTransition(transition, mTargetTask == null ? started.getTask() : mTargetTask, remoteTransition, null /* displayChange */); } else if (result == START_SUCCESS && mStartActivity.isState(RESUMED)) { // Do nothing if the activity is started and is resumed directly. } else if (isStarted) { // Make the collecting transition wait until this request is ready. - transitionController.setReady(started, false); + if (transition != null) { + transition.setReady(started, false); + } } return startedActivityRootTask; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f23211b98b85..5e030661c668 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2116,12 +2116,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.w(TAG, "removeTask: No task remove with id=" + taskId); return false; } - - if (task.isLeafTask()) { - mTaskSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-task"); - } else { - mTaskSupervisor.removeRootTask(task); - } + removeTask(task); return true; } finally { Binder.restoreCallingIdentity(ident); @@ -2129,6 +2124,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + void removeTask(@NonNull Task task) { + if (task.isLeafTask()) { + mTaskSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-task"); + } else { + mTaskSupervisor.removeRootTask(task); + } + } + @Override public void removeAllVisibleRecentTasks() { mAmInternal.enforceCallingPermission(REMOVE_TASKS, "removeAllVisibleRecentTasks()"); @@ -2938,7 +2941,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } getTransitionController().requestStartTransition(transition, task, null /* remoteTransition */, null /* displayChange */); - getTransitionController().collect(task); + transition.collect(task); task.resize(bounds, resizeMode, preserveWindow); transition.setReady(task, true); }); @@ -3768,6 +3771,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Shell calls back into Core with the entry bounds to be applied with startWCT. final Transition enterPipTransition = new Transition(TRANSIT_PIP, 0 /* flags */, getTransitionController(), mWindowManager.mSyncEngine); + r.setPictureInPictureParams(params); enterPipTransition.setPipActivity(r); r.mAutoEnteringPip = isAutoEnter; getTransitionController().startCollectOrQueue(enterPipTransition, (deferred) -> { @@ -4622,7 +4626,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return kept; } - /** Update default (global) configuration and notify listeners about changes. */ + /** + * Updates default (global) configuration and notifies listeners about changes. + * + * @param values The new configuration. It must always be a new instance from the caller, and + * it won't be modified after calling this method. + */ int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale, boolean persistent, int userId) { @@ -4636,24 +4645,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ProtoLog.i(WM_DEBUG_CONFIGURATION, "Updating global configuration " + "to: %s", values); writeConfigurationChanged(changes); - FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED, - values.colorMode, - values.densityDpi, - values.fontScale, - values.hardKeyboardHidden, - values.keyboard, - values.keyboardHidden, - values.mcc, - values.mnc, - values.navigation, - values.navigationHidden, - values.orientation, - values.screenHeightDp, - values.screenLayout, - values.screenWidthDp, - values.smallestScreenWidthDp, - values.touchscreen, - values.uiMode); // Note: certain tests currently run as platform_app which is not allowed // to set debug system properties. To ensure that system properties are set @@ -4701,13 +4692,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // resources have that config before following boot code is executed. mSystemThread.applyConfigurationToResources(mTempConfig); - if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) { - final Message msg = PooledLambda.obtainMessage( - ActivityTaskManagerService::sendPutConfigurationForUserMsg, - this, userId, new Configuration(mTempConfig)); - mH.sendMessage(msg); - } - SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap(); for (int i = pidMap.size() - 1; i >= 0; i--) { final int pid = pidMap.keyAt(i); @@ -4717,19 +4701,32 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { app.onConfigurationChanged(mTempConfig); } - final Message msg = PooledLambda.obtainMessage( - ActivityManagerInternal::broadcastGlobalConfigurationChanged, - mAmInternal, changes, initLocale); - mH.sendMessage(msg); + final Configuration configurationForSettings = + persistent && Settings.System.hasInterestingConfigurationChanges(changes) + ? new Configuration(mTempConfig) : null; + mH.post(() -> { + FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED, + values.colorMode, values.densityDpi, values.fontScale, + values.hardKeyboardHidden, values.keyboard, values.keyboardHidden, + values.mcc, values.mnc, values.navigation, values.navigationHidden, + values.orientation, values.screenHeightDp, values.screenLayout, + values.screenWidthDp, values.smallestScreenWidthDp, values.touchscreen, + values.uiMode); + if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) { + FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED, + values.orientation); + } + if (configurationForSettings != null) { + Settings.System.putConfigurationForUser(mContext.getContentResolver(), + configurationForSettings, userId); + } + mAmInternal.broadcastGlobalConfigurationChanged(changes, initLocale); + }); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RootConfigChange"); // Update stored global config and notify everyone about the change. mRootWindowContainer.onConfigurationChanged(mTempConfig); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) { - FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED, - values.orientation); - } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return changes; @@ -4879,11 +4876,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mWindowManager.setEventDispatching(booted && !mShuttingDown); } - private void sendPutConfigurationForUserMsg(int userId, Configuration config) { - final ContentResolver resolver = mContext.getContentResolver(); - Settings.System.putConfigurationForUser(resolver, config, userId); - } - boolean isActivityStartsLoggingEnabled() { return mAmInternal.isActivityStartsLoggingEnabled(); } @@ -6781,7 +6773,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { // The output proto of "activity --proto activities" mRootWindowContainer.dumpDebug( - proto, ROOT_WINDOW_CONTAINER, WindowTraceLogLevel.ALL); + proto, ROOT_WINDOW_CONTAINER, WindowTracingLogLevel.ALL); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 8ef2693ec327..1446c353d9d4 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1528,9 +1528,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } mService.deferWindowLayout(); - final Transition newTransition = task.mTransitionController.isShellTransitionsEnabled() - ? task.mTransitionController.isCollecting() ? null - : task.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null; + boolean newTransition = false; + Transition transition = task.mTransitionController.getCollectingTransition(); + if (transition == null && task.mTransitionController.isShellTransitionsEnabled()) { + transition = task.mTransitionController.createTransition(TRANSIT_TO_FRONT); + newTransition = true; + } task.mTransitionController.collect(task); reason = reason + " findTaskToMoveToFront"; boolean reparented = false; @@ -1574,8 +1577,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // transition to avoid delaying the starting window. r.showStartingWindow(true /* taskSwitch */); } - if (newTransition != null) { - task.mTransitionController.requestStartTransition(newTransition, task, + if (newTransition) { + task.mTransitionController.requestStartTransition(transition, task, options != null ? options.getRemoteTransition() : null, null /* displayChange */); } @@ -1644,7 +1647,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mService.deferWindowLayout(); try { - rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); if (rootTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) { rootTask.setBounds(null); } @@ -1705,7 +1708,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Prevent recursion. return; } - final Transition transit = task.mTransitionController.requestCloseTransitionIfNeeded(task); + Transition transit = task.mTransitionController.requestCloseTransitionIfNeeded(task); + if (transit == null) { + transit = task.mTransitionController.getCollectingTransition(); + } if (transit != null) { transit.collectClose(task); if (!task.mTransitionController.useFullReadyTracking()) { @@ -1717,8 +1723,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // before anything that may need it to wait (setReady(false)). transit.setReady(task, true); } - } else if (task.mTransitionController.isCollecting()) { - task.mTransitionController.getCollectingTransition().collectClose(task); } // Consume the stopping activities immediately so activity manager won't skip killing // the process because it is still foreground state, i.e. RESUMED -> PAUSING set from diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java index d2f3d1db16a7..cd795ae167ea 100644 --- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java @@ -233,7 +233,8 @@ class AppCompatAspectRatioOverrides { return mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); } - private float getDisplaySizeMinAspectRatio() { + @VisibleForTesting + float getDisplaySizeMinAspectRatio() { final DisplayArea displayArea = mActivityRecord.getDisplayArea(); if (displayArea == null) { return mActivityRecord.info.getMinAspectRatio(); @@ -263,7 +264,13 @@ class AppCompatAspectRatioOverrides { && cameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)); } - @VisibleForTesting + /** + * Returns the value of the user aspect ratio override property. If unset, return {@code true}. + */ + boolean getAllowUserAspectRatioOverridePropertyValue() { + return !mAllowUserAspectRatioOverrideOptProp.isFalse(); + } + int getUserMinAspectRatioOverrideCode() { try { return mActivityRecord.mAtmService.getPackageManager() diff --git a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java index 1562cf64ad96..a42b8794b43d 100644 --- a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java @@ -24,6 +24,7 @@ import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.widget.Toast; +import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; /** @@ -32,7 +33,8 @@ import com.android.window.flags.Flags; class AppCompatCameraPolicy { @Nullable - private final CameraStateMonitor mCameraStateMonitor; + @VisibleForTesting + final CameraStateMonitor mCameraStateMonitor; @Nullable private final ActivityRefresher mActivityRefresher; @Nullable @@ -122,6 +124,9 @@ class AppCompatCameraPolicy { } void start() { + if (mDisplayRotationCompatPolicy != null) { + mDisplayRotationCompatPolicy.start(); + } if (mCameraCompatFreeformPolicy != null) { mCameraCompatFreeformPolicy.start(); } @@ -150,6 +155,10 @@ class AppCompatCameraPolicy { return mCameraCompatFreeformPolicy != null; } + boolean hasCameraStateMonitor() { + return mCameraStateMonitor != null; + } + @ScreenOrientation int getOrientation() { return mDisplayRotationCompatPolicy != null diff --git a/services/core/java/com/android/server/wm/AppCompatConfiguration.java b/services/core/java/com/android/server/wm/AppCompatConfiguration.java index ffa4251d0ded..42378aaf6c05 100644 --- a/services/core/java/com/android/server/wm/AppCompatConfiguration.java +++ b/services/core/java/com/android/server/wm/AppCompatConfiguration.java @@ -30,6 +30,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wm.utils.DimenPxIntSupplier; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.function.Function; @@ -1382,6 +1383,26 @@ final class AppCompatConfiguration { setUserAppAspectRatioFullscreenOverrideEnabled(false); } + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + // TODO(b/359438445): Add more useful information to dump(). + pw.println(prefix + " letterboxPositionForHorizontalReachability=" + + letterboxHorizontalReachabilityPositionToString( + getLetterboxPositionForHorizontalReachability( + /* isInFullScreenBookMode */ false))); + pw.println(prefix + " letterboxPositionForVerticalReachability=" + + letterboxVerticalReachabilityPositionToString( + getLetterboxPositionForVerticalReachability( + /* isInFullScreenTabletopMode */ false))); + pw.println(prefix + " fixedOrientationLetterboxAspectRatio=" + + getFixedOrientationLetterboxAspectRatio()); + pw.println(prefix + " defaultMinAspectRatioForUnresizableApps=" + + getDefaultMinAspectRatioForUnresizableApps()); + pw.println(prefix + " isSplitScreenAspectRatioForUnresizableAppsEnabled=" + + getIsSplitScreenAspectRatioForUnresizableAppsEnabled()); + pw.println(prefix + " isDisplayAspectRatioEnabledForFixedOrientationLetterbox=" + + getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()); + } + /** * Checks whether the multiplier is between [0,1]. * diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java index 42900512de5d..3c3b77374d70 100644 --- a/services/core/java/com/android/server/wm/AppCompatController.java +++ b/services/core/java/com/android/server/wm/AppCompatController.java @@ -21,6 +21,8 @@ import android.content.pm.PackageManager; import com.android.server.wm.utils.OptPropFactory; +import java.io.PrintWriter; + /** * Allows the interaction with all the app compat policies and configurations */ @@ -37,6 +39,8 @@ class AppCompatController { @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; @NonNull + private final DesktopAppCompatAspectRatioPolicy mDesktopAppCompatAspectRatioPolicy; + @NonNull private final AppCompatOverrides mAppCompatOverrides; @NonNull private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery; @@ -59,7 +63,10 @@ class AppCompatController { mTransparentPolicy, mAppCompatOverrides); mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(mActivityRecord, wmService.mAppCompatConfiguration); - mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(mActivityRecord); + mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(mActivityRecord, + wmService.mAppCompatConfiguration); + mDesktopAppCompatAspectRatioPolicy = new DesktopAppCompatAspectRatioPolicy(activityRecord, + mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration); } @NonNull @@ -78,6 +85,11 @@ class AppCompatController { } @NonNull + DesktopAppCompatAspectRatioPolicy getDesktopAppCompatAspectRatioPolicy() { + return mDesktopAppCompatAspectRatioPolicy; + } + + @NonNull AppCompatOverrides getAppCompatOverrides() { return mAppCompatOverrides; } @@ -140,4 +152,9 @@ class AppCompatController { return mAppCompatOverrides.getAppCompatLetterboxOverrides(); } + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + getTransparentPolicy().dump(pw, prefix); + getAppCompatLetterboxPolicy().dump(pw, prefix); + } + } diff --git a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java index d602c47d26c0..afc6506f9091 100644 --- a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.AppCompatConfiguration.letterboxBackgroundTypeToString; import android.annotation.NonNull; import android.annotation.Nullable; @@ -32,6 +33,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.LetterboxDetails; import com.android.server.wm.AppCompatConfiguration.LetterboxBackgroundType; +import java.io.PrintWriter; + /** * Encapsulates the logic for the Letterboxing policy. */ @@ -43,15 +46,19 @@ class AppCompatLetterboxPolicy { private final LetterboxPolicyState mLetterboxPolicyState; @NonNull private final AppCompatRoundedCorners mAppCompatRoundedCorners; + @NonNull + private final AppCompatConfiguration mAppCompatConfiguration; private boolean mLastShouldShowLetterboxUi; - AppCompatLetterboxPolicy(@NonNull ActivityRecord activityRecord) { + AppCompatLetterboxPolicy(@NonNull ActivityRecord activityRecord, + @NonNull AppCompatConfiguration appCompatConfiguration) { mActivityRecord = activityRecord; mLetterboxPolicyState = new LetterboxPolicyState(); // TODO (b/358334569) Improve cutout logic dependency on app compat. mAppCompatRoundedCorners = new AppCompatRoundedCorners(mActivityRecord, this::isLetterboxedNotForDisplayCutout); + mAppCompatConfiguration = appCompatConfiguration; } /** Cleans up {@link Letterbox} if it exists.*/ @@ -156,6 +163,38 @@ class AppCompatLetterboxPolicy { return mAppCompatRoundedCorners.getRoundedCornersRadius(mainWindow); } + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + final WindowState mainWin = mActivityRecord.findMainWindow(); + if (mainWin == null) { + return; + } + boolean areBoundsLetterboxed = mainWin.areAppWindowBoundsLetterboxed(); + pw.println(prefix + "areBoundsLetterboxed=" + areBoundsLetterboxed); + pw.println(prefix + "isLetterboxRunning=" + isRunning()); + if (!areBoundsLetterboxed) { + return; + } + pw.println(prefix + " letterboxReason=" + + AppCompatUtils.getLetterboxReasonString(mActivityRecord, mainWin)); + mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy().dump(pw, prefix); + final AppCompatLetterboxOverrides letterboxOverride = mActivityRecord.mAppCompatController + .getAppCompatLetterboxOverrides(); + pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString( + letterboxOverride.getLetterboxBackgroundColor().toArgb())); + pw.println(prefix + " letterboxBackgroundType=" + + letterboxBackgroundTypeToString(letterboxOverride.getLetterboxBackgroundType())); + pw.println(prefix + " letterboxCornerRadius=" + getRoundedCornersRadius(mainWin)); + if (letterboxOverride.getLetterboxBackgroundType() == LETTERBOX_BACKGROUND_WALLPAPER) { + pw.println(prefix + " isLetterboxWallpaperBlurSupported=" + + letterboxOverride.isLetterboxWallpaperBlurSupported()); + pw.println(prefix + " letterboxBackgroundWallpaperDarkScrimAlpha=" + + letterboxOverride.getLetterboxWallpaperDarkScrimAlpha()); + pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius=" + + letterboxOverride.getLetterboxWallpaperBlurRadiusPx()); + } + mAppCompatConfiguration.dump(pw, prefix); + } + private void updateWallpaperForLetterbox(@NonNull WindowState mainWindow) { final AppCompatLetterboxOverrides letterboxOverrides = mActivityRecord .mAppCompatController.getAppCompatLetterboxOverrides(); diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java index c3bf116e227d..d03a80387657 100644 --- a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java @@ -33,6 +33,7 @@ import android.graphics.Rect; import com.android.internal.annotations.VisibleForTesting; +import java.io.PrintWriter; import java.util.function.Supplier; /** @@ -74,6 +75,25 @@ class AppCompatReachabilityPolicy { handleVerticalDoubleTap(y); } + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + final AppCompatReachabilityOverrides reachabilityOverrides = + mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides(); + pw.println(prefix + " isVerticalThinLetterboxed=" + reachabilityOverrides + .isVerticalThinLetterboxed()); + pw.println(prefix + " isHorizontalThinLetterboxed=" + reachabilityOverrides + .isHorizontalThinLetterboxed()); + pw.println(prefix + " isHorizontalReachabilityEnabled=" + + reachabilityOverrides.isHorizontalReachabilityEnabled()); + pw.println(prefix + " isVerticalReachabilityEnabled=" + + reachabilityOverrides.isVerticalReachabilityEnabled()); + pw.println(prefix + " letterboxHorizontalPositionMultiplier=" + + reachabilityOverrides.getHorizontalPositionMultiplier( + mActivityRecord.getParent().getConfiguration())); + pw.println(prefix + " letterboxVerticalPositionMultiplier=" + + reachabilityOverrides.getVerticalPositionMultiplier( + mActivityRecord.getParent().getConfiguration())); + } + private void handleHorizontalDoubleTap(int x) { final AppCompatReachabilityOverrides reachabilityOverrides = mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides(); diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java index 94ad61f3f4de..e3ff85171c0e 100644 --- a/services/core/java/com/android/server/wm/AppCompatUtils.java +++ b/services/core/java/com/android/server/wm/AppCompatUtils.java @@ -187,6 +187,8 @@ final class AppCompatUtils { appCompatTaskInfo.setTopActivityLetterboxed(top.areBoundsLetterboxed()); appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = top.mAppCompatController .getAppCompatCameraOverrides().getFreeformCameraCompatMode(); + appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController + .getDesktopAppCompatAspectRatioPolicy().hasMinAspectRatioOverride(task)); } /** diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 89e10d36caed..87867f6ab7d2 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -283,8 +283,10 @@ class BackNavigationController { // keyguard locked and activities are unable to show when locked. backType = BackNavigationInfo.TYPE_CALLBACK; } - } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask)) { + } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask) + || currentTask.getWindowConfiguration().tasksAreFloating()) { // Do not predict if current task is in task locked. + // Also, it is unable to play cross task animation for floating task. backType = BackNavigationInfo.TYPE_CALLBACK; } else { // Check back-to-home or cross-task @@ -367,7 +369,7 @@ class BackNavigationController { // client process to prevent the unexpected relayout when handling the back // animation. for (int i = prevActivities.size() - 1; i >= 0; --i) { - prevActivities.get(i).setDeferHidingClient(true); + prevActivities.get(i).setDeferHidingClient(); } } else { scheduleAnimation(builder); diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 02c8a4999f4d..20c5f02aaee2 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -1506,10 +1506,13 @@ public class BackgroundActivityStartController { PackageManager pm = mService.mContext.getPackageManager(); ApplicationInfo applicationInfo; + final int sourceUserId = UserHandle.getUserId(sourceUid); try { - applicationInfo = pm.getApplicationInfo(packageName, 0); + applicationInfo = pm.getApplicationInfoAsUser(packageName, /* flags= */ 0, + sourceUserId); } catch (PackageManager.NameNotFoundException e) { - Slog.wtf(TAG, "Package name: " + packageName + " not found."); + Slog.wtf(TAG, "Package name: " + packageName + " not found for user " + + sourceUserId); return bas.optedIn(ar); } diff --git a/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java b/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java index 9b142f280b31..dda39a6a12da 100644 --- a/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java +++ b/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java @@ -60,6 +60,11 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa @Nullable private Task mCameraTask; + /** + * Value toggled on {@link #start()} to {@code true} and on {@link #dispose()} to {@code false}. + */ + private boolean mIsRunning; + CameraCompatFreeformPolicy(@NonNull DisplayContent displayContent, @NonNull CameraStateMonitor cameraStateMonitor, @NonNull ActivityRefresher activityRefresher) { @@ -71,12 +76,19 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa void start() { mCameraStateMonitor.addCameraStateListener(this); mActivityRefresher.addEvaluator(this); + mIsRunning = true; } /** Releases camera callback listener. */ void dispose() { mCameraStateMonitor.removeCameraStateListener(this); mActivityRefresher.removeEvaluator(this); + mIsRunning = false; + } + + @VisibleForTesting + boolean isRunning() { + return mIsRunning; } // Refreshing only when configuration changes after rotation or camera split screen aspect ratio diff --git a/services/core/java/com/android/server/wm/CameraStateMonitor.java b/services/core/java/com/android/server/wm/CameraStateMonitor.java index 63c90ff93224..8bfef6d5d218 100644 --- a/services/core/java/com/android/server/wm/CameraStateMonitor.java +++ b/services/core/java/com/android/server/wm/CameraStateMonitor.java @@ -26,6 +26,7 @@ import android.os.Handler; import android.util.ArraySet; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import java.util.ArrayList; @@ -73,6 +74,12 @@ class CameraStateMonitor { private final ArrayList<CameraCompatStateListener> mCameraStateListeners = new ArrayList<>(); + /** + * Value toggled on {@link #startListeningToCameraState()} to {@code true} and on {@link + * #dispose()} to {@code false}. + */ + private boolean mIsRunning; + private final CameraManager.AvailabilityCallback mAvailabilityCallback = new CameraManager.AvailabilityCallback() { @Override @@ -101,6 +108,7 @@ class CameraStateMonitor { void startListeningToCameraState() { mCameraManager.registerAvailabilityCallback( mWmService.mContext.getMainExecutor(), mAvailabilityCallback); + mIsRunning = true; } /** Releases camera callback listener. */ @@ -108,6 +116,12 @@ class CameraStateMonitor { if (mCameraManager != null) { mCameraManager.unregisterAvailabilityCallback(mAvailabilityCallback); } + mIsRunning = false; + } + + @VisibleForTesting + boolean isRunning() { + return mIsRunning; } void addCameraStateListener(CameraCompatStateListener listener) { diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 3ebaf03c4a31..9be3f436b819 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -255,8 +255,18 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { inOutConfig.windowConfiguration.setAppBounds( newParentConfiguration.windowConfiguration.getBounds()); outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); - outAppBounds.inset(displayContent.getDisplayPolicy() - .getDecorInsetsInfo(rotation, dw, dh).mOverrideNonDecorInsets); + if (inOutConfig.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + final DisplayPolicy.DecorInsets.Info decor = + displayContent.getDisplayPolicy().getDecorInsetsInfo(rotation, dw, dh); + if (outAppBounds.contains(decor.mOverrideNonDecorFrame)) { + outAppBounds.intersect(decor.mOverrideNonDecorFrame); + } + } else { + // TODO(b/358509380): Handle other windowing mode like split screen and freeform + // cases correctly. + outAppBounds.inset(displayContent.getDisplayPolicy() + .getDecorInsetsInfo(rotation, dw, dh).mOverrideNonDecorInsets); + } } float density = inOutConfig.densityDpi; if (density == Configuration.DENSITY_DPI_UNDEFINED) { @@ -807,23 +817,23 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { */ @CallSuper protected void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { final long token = proto.start(fieldId); - if (logLevel == WindowTraceLogLevel.ALL || mHasOverrideConfiguration) { + if (logLevel == WindowTracingLogLevel.ALL || mHasOverrideConfiguration) { mRequestedOverrideConfiguration.dumpDebug(proto, OVERRIDE_CONFIGURATION, - logLevel == WindowTraceLogLevel.CRITICAL); + logLevel == WindowTracingLogLevel.CRITICAL); } // Unless trace level is set to `WindowTraceLogLevel.ALL` don't dump anything that isn't // required to mitigate performance overhead - if (logLevel == WindowTraceLogLevel.ALL) { + if (logLevel == WindowTracingLogLevel.ALL) { mFullConfiguration.dumpDebug(proto, FULL_CONFIGURATION, false /* critical */); mMergedOverrideConfiguration.dumpDebug(proto, MERGED_OVERRIDE_CONFIGURATION, false /* critical */); } - if (logLevel == WindowTraceLogLevel.TRIM) { + if (logLevel == WindowTracingLogLevel.TRIM) { // Required for Fass to automatically detect pip transitions in Winscope traces dumpDebugWindowingMode(proto); } diff --git a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java new file mode 100644 index 000000000000..b936556c3264 --- /dev/null +++ b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; + +import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; +import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; + +import android.annotation.NonNull; +import android.app.WindowConfiguration; +import android.content.pm.ActivityInfo; +import android.graphics.Rect; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; + +// TODO(b/359217664): Consider refactoring into AppCompatAspectRatioPolicy. +/** + * Encapsulate app compat aspect ratio policy logic specific for desktop windowing initial bounds + * calculation. + */ +public class DesktopAppCompatAspectRatioPolicy { + + @NonNull + private final AppCompatOverrides mAppCompatOverrides; + @NonNull + private final AppCompatConfiguration mAppCompatConfiguration; + @NonNull + private final ActivityRecord mActivityRecord; + @NonNull + private final TransparentPolicy mTransparentPolicy; + + DesktopAppCompatAspectRatioPolicy(@NonNull ActivityRecord activityRecord, + @NonNull AppCompatOverrides appCompatOverrides, + @NonNull TransparentPolicy transparentPolicy, + @NonNull AppCompatConfiguration appCompatConfiguration) { + mActivityRecord = activityRecord; + mAppCompatOverrides = appCompatOverrides; + mTransparentPolicy = transparentPolicy; + mAppCompatConfiguration = appCompatConfiguration; + } + + /** + * Calculates the final aspect ratio of an launching activity based on the task it will be + * launched in. Takes into account any min or max aspect ratio constraints. + */ + float calculateAspectRatio(@NonNull Task task) { + final float maxAspectRatio = getMaxAspectRatio(); + final float minAspectRatio = getMinAspectRatio(task); + float desiredAspectRatio = 0; + desiredAspectRatio = getDesiredAspectRatio(task); + if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { + desiredAspectRatio = maxAspectRatio; + } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { + desiredAspectRatio = minAspectRatio; + } + return desiredAspectRatio; + } + + /** + * Returns the aspect ratio desired by the system for current activity, not taking into account + * any min or max aspect ratio constraints. + */ + @VisibleForTesting + float getDesiredAspectRatio(@NonNull Task task) { + final float letterboxAspectRatioOverride = getFixedOrientationLetterboxAspectRatio(task); + // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will + // be respected in #calculateAspectRatio. + if (isDefaultMultiWindowLetterboxAspectRatioDesired(task)) { + return DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; + } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { + return letterboxAspectRatioOverride; + } + return AppCompatUtils.computeAspectRatio(task.getDisplayArea().getBounds()); + } + + /** + * Determines the letterbox aspect ratio for an application based on its orientation and + * resizability. + */ + private float getFixedOrientationLetterboxAspectRatio(@NonNull Task task) { + return mActivityRecord.shouldCreateCompatDisplayInsets() + ? getDefaultMinAspectRatioForUnresizableApps(task) + : getDefaultMinAspectRatio(task); + } + + /** + * Calculates the aspect ratio of the available display area when an app enters split-screen on + * a given device, taking into account any dividers and insets. + */ + private float getSplitScreenAspectRatio(@NonNull Task task) { + // Getting the same aspect ratio that apps get in split screen. + final DisplayArea displayArea = task.getDisplayArea(); + final int dividerWindowWidth = + mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( + R.dimen.docked_stack_divider_thickness); + final int dividerInsets = + mActivityRecord.mWmService.mContext.getResources().getDimensionPixelSize( + R.dimen.docked_stack_divider_insets); + final int dividerSize = dividerWindowWidth - dividerInsets * 2; + final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); + if (bounds.width() >= bounds.height()) { + bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); + bounds.right = bounds.centerX(); + } else { + bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); + bounds.bottom = bounds.centerY(); + } + return AppCompatUtils.computeAspectRatio(bounds); + } + + + /** + * Returns the minimum aspect ratio for unresizable apps as determined by the system. + */ + private float getDefaultMinAspectRatioForUnresizableApps(@NonNull Task task) { + if (!mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled()) { + return mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() + > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO + ? mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps() + : getDefaultMinAspectRatio(task); + } + + return getSplitScreenAspectRatio(task); + } + + /** + * Returns the default minimum aspect ratio for apps as determined by the system. + */ + private float getDefaultMinAspectRatio(@NonNull Task task) { + if (!mAppCompatConfiguration.getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()) { + return mAppCompatConfiguration.getFixedOrientationLetterboxAspectRatio(); + } + return getDisplayAreaMinAspectRatio(task); + } + + /** + * Calculates the aspect ratio of the available display area. + */ + private float getDisplayAreaMinAspectRatio(@NonNull Task task) { + final DisplayArea displayArea = task.getDisplayArea(); + final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds()); + return AppCompatUtils.computeAspectRatio(bounds); + } + + /** + * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode + * should be used. + */ + private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(@NonNull Task task) { + final DisplayContent dc = task.mDisplayContent; + final int windowingMode = task.getDisplayArea().getWindowingMode(); + return WindowConfiguration.inMultiWindowMode(windowingMode) + && !dc.getIgnoreOrientationRequest(); + } + + /** + * Returns the min aspect ratio of this activity. + */ + private float getMinAspectRatio(@NonNull Task task) { + if (mTransparentPolicy.isRunning()) { + return mTransparentPolicy.getInheritedMinAspectRatio(); + } + + final ActivityInfo info = mActivityRecord.info; + if (info.applicationInfo == null) { + return info.getMinAspectRatio(); + } + + final AppCompatAspectRatioOverrides aspectRatioOverrides = + mAppCompatOverrides.getAppCompatAspectRatioOverrides(); + if (shouldApplyUserMinAspectRatioOverride(task)) { + return aspectRatioOverrides.getUserMinAspectRatio(); + } + + if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() + && !mAppCompatOverrides.getAppCompatCameraOverrides() + .shouldOverrideMinAspectRatioForCamera()) { + return info.getMinAspectRatio(); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY) + && !ActivityInfo.isFixedOrientationPortrait( + mActivityRecord.getOverrideOrientation())) { + return info.getMinAspectRatio(); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN) + && isFullscreenPortrait(task)) { + return info.getMinAspectRatio(); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN)) { + return Math.max(aspectRatioOverrides.getSplitScreenAspectRatio(), + info.getMinAspectRatio()); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_LARGE)) { + return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE, + info.getMinAspectRatio()); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_MEDIUM)) { + return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE, + info.getMinAspectRatio()); + } + + if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_SMALL)) { + return Math.max(ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE, + info.getMinAspectRatio()); + } + return info.getMinAspectRatio(); + } + + /** + * Returns the max aspect ratio of this activity. + */ + private float getMaxAspectRatio() { + if (mTransparentPolicy.isRunning()) { + return mTransparentPolicy.getInheritedMaxAspectRatio(); + } + return mActivityRecord.info.getMaxAspectRatio(); + } + + /** + * Whether an applications minimum aspect ratio has been overridden. + */ + boolean hasMinAspectRatioOverride(@NonNull Task task) { + return mActivityRecord.info.getMinAspectRatio() < getMinAspectRatio(task); + } + + /** + * Whether we should apply the user aspect ratio override to the min aspect ratio for the + * current app. + */ + boolean shouldApplyUserMinAspectRatioOverride(@NonNull Task task) { + if (!shouldEnableUserAspectRatioSettings(task)) { + return false; + } + + final int userAspectRatioCode = mAppCompatOverrides.getAppCompatAspectRatioOverrides() + .getUserMinAspectRatioOverrideCode(); + + return userAspectRatioCode != USER_MIN_ASPECT_RATIO_UNSET + && userAspectRatioCode != USER_MIN_ASPECT_RATIO_APP_DEFAULT + && userAspectRatioCode != USER_MIN_ASPECT_RATIO_FULLSCREEN; + } + + /** + * Whether we should enable users to resize the current app. + */ + private boolean shouldEnableUserAspectRatioSettings(@NonNull Task task) { + // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has + // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null, + // the current app doesn't opt-out so the first part of the predicate is true. + return mAppCompatOverrides.getAppCompatAspectRatioOverrides() + .getAllowUserAspectRatioOverridePropertyValue() + && mAppCompatConfiguration.isUserAppAspectRatioSettingsEnabled() + && task.mDisplayContent.getIgnoreOrientationRequest(); + } + + /** + * Returns {@code true} if the task window is portrait and fullscreen. + */ + private boolean isFullscreenPortrait(@NonNull Task task) { + return task.getConfiguration().orientation == ORIENTATION_PORTRAIT + && task.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN; + } +} diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java index 8f1828d741c5..c3db7dd7bfaf 100644 --- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java +++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java @@ -16,31 +16,28 @@ package com.android.server.wm; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; +import static android.content.pm.ActivityInfo.isFixedOrientation; import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; -import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; -import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; -import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.LaunchParamsUtil.applyLayoutGravity; import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; -import android.app.AppCompatTaskInfo; import android.app.TaskInfo; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; +import android.content.pm.ActivityInfo.ScreenOrientation; +import android.content.pm.ActivityInfo.WindowLayout; import android.graphics.Rect; import android.os.SystemProperties; import android.util.Size; import android.view.Gravity; -import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; import com.android.server.wm.utils.DesktopModeFlagsUtil; import java.util.function.Consumer; @@ -60,7 +57,7 @@ public final class DesktopModeBoundsCalculator { * Updates launch bounds for an activity with respect to its activity options, window layout, * android manifest and task configuration. */ - static void updateInitialBounds(@NonNull Task task, @Nullable ActivityInfo.WindowLayout layout, + static void updateInitialBounds(@NonNull Task task, @Nullable WindowLayout layout, @Nullable ActivityRecord activity, @Nullable ActivityOptions options, @NonNull Rect outBounds, @NonNull Consumer<String> logger) { // Use stable frame instead of raw frame to avoid launching freeform windows on top of @@ -98,7 +95,8 @@ public final class DesktopModeBoundsCalculator { * fullscreen size, aspect ratio, orientation and resizability to calculate an area this is * compatible with the applications previous configuration. */ - private static @NonNull Rect calculateInitialBounds(@NonNull Task task, + @NonNull + private static Rect calculateInitialBounds(@NonNull Task task, @NonNull ActivityRecord activity, @NonNull Rect stableBounds ) { final TaskInfo taskInfo = task.getTaskInfo(); @@ -116,18 +114,19 @@ public final class DesktopModeBoundsCalculator { // applied. return centerInScreen(idealSize, screenBounds); } - // TODO(b/353457301): Replace with app compat aspect ratio method when refactoring complete. - float appAspectRatio = calculateAspectRatio(task, activity); + final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy = + activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + float appAspectRatio = desktopAppCompatAspectRatioPolicy.calculateAspectRatio(task); final float tdaWidth = stableBounds.width(); final float tdaHeight = stableBounds.height(); - final int activityOrientation = activity.getOverrideOrientation(); + final int activityOrientation = getActivityOrientation(activity, task); final Size initialSize = switch (taskInfo.configuration.orientation) { case ORIENTATION_LANDSCAPE -> { // Device in landscape orientation. if (appAspectRatio == 0) { appAspectRatio = 1; } - if (taskInfo.isResizeable) { + if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) { if (isFixedOrientationPortrait(activityOrientation)) { // For portrait resizeable activities, respect apps fullscreen width but // apply ideal size height. @@ -139,14 +138,13 @@ public final class DesktopModeBoundsCalculator { } // If activity is unresizeable, regardless of orientation, calculate maximum size // (within the ideal size) maintaining original aspect ratio. - yield maximizeSizeGivenAspectRatio( - activity.getOverrideOrientation(), idealSize, appAspectRatio); + yield maximizeSizeGivenAspectRatio(activityOrientation, idealSize, appAspectRatio); } case ORIENTATION_PORTRAIT -> { // Device in portrait orientation. final int customPortraitWidthForLandscapeApp = screenBounds.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); - if (taskInfo.isResizeable) { + if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) { if (isFixedOrientationLandscape(activityOrientation)) { if (appAspectRatio == 0) { appAspectRatio = tdaWidth / (tdaWidth - 1); @@ -180,11 +178,38 @@ public final class DesktopModeBoundsCalculator { } /** + * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was + * unresizeable. + */ + private static boolean canChangeAspectRatio( + @NonNull DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy, + @NonNull TaskInfo taskInfo, @NonNull Task task) { + return taskInfo.isResizeable + && !desktopAppCompatAspectRatioPolicy.hasMinAspectRatioOverride(task); + } + + private static @ScreenOrientation int getActivityOrientation( + @NonNull ActivityRecord activity, @NonNull Task task) { + final int activityOrientation = activity.getOverrideOrientation(); + final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy = + activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + if (desktopAppCompatAspectRatioPolicy.shouldApplyUserMinAspectRatioOverride(task) + && (!isFixedOrientation(activityOrientation) + || activityOrientation == SCREEN_ORIENTATION_LOCKED)) { + // If a user aspect ratio override should be applied, treat the activity as portrait if + // it has not specified a fix orientation. + return SCREEN_ORIENTATION_PORTRAIT; + } + return activityOrientation; + } + + /** * Calculates the largest size that can fit in a given area while maintaining a specific aspect * ratio. */ - private static @NonNull Size maximizeSizeGivenAspectRatio( - @ActivityInfo.ScreenOrientation int orientation, + @NonNull + private static Size maximizeSizeGivenAspectRatio( + @ScreenOrientation int orientation, @NonNull Size targetArea, float aspectRatio ) { @@ -229,68 +254,11 @@ public final class DesktopModeBoundsCalculator { } /** - * Calculates the aspect ratio of an activity from its fullscreen bounds. - */ - @VisibleForTesting - static float calculateAspectRatio(@NonNull Task task, @NonNull ActivityRecord activity) { - final TaskInfo taskInfo = task.getTaskInfo(); - final float fullscreenWidth = task.getDisplayArea().getBounds().width(); - final float fullscreenHeight = task.getDisplayArea().getBounds().height(); - final float maxAspectRatio = activity.getMaxAspectRatio(); - final float minAspectRatio = activity.getMinAspectRatio(); - float desiredAspectRatio = 0; - if (taskInfo.isRunning) { - final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo; - final int appLetterboxWidth = - taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth; - final int appLetterboxHeight = - taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight; - if (appCompatTaskInfo.isTopActivityLetterboxed()) { - desiredAspectRatio = (float) Math.max(appLetterboxWidth, appLetterboxHeight) - / Math.min(appLetterboxWidth, appLetterboxHeight); - } else { - desiredAspectRatio = Math.max(fullscreenHeight, fullscreenWidth) - / Math.min(fullscreenHeight, fullscreenWidth); - } - } else { - final float letterboxAspectRatioOverride = - getFixedOrientationLetterboxAspectRatio(activity, task); - if (!task.mDisplayContent.getIgnoreOrientationRequest()) { - desiredAspectRatio = DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; - } else if (letterboxAspectRatioOverride - > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { - desiredAspectRatio = letterboxAspectRatioOverride; - } - } - // If the activity matches display orientation, the display aspect ratio should be used - if (activityMatchesDisplayOrientation( - taskInfo.configuration.orientation, - activity.getOverrideOrientation())) { - desiredAspectRatio = Math.max(fullscreenWidth, fullscreenHeight) - / Math.min(fullscreenWidth, fullscreenHeight); - } - if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { - desiredAspectRatio = maxAspectRatio; - } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { - desiredAspectRatio = minAspectRatio; - } - return desiredAspectRatio; - } - - private static boolean activityMatchesDisplayOrientation( - @Configuration.Orientation int deviceOrientation, - @ActivityInfo.ScreenOrientation int activityOrientation) { - if (deviceOrientation == ORIENTATION_PORTRAIT) { - return isFixedOrientationPortrait(activityOrientation); - } - return isFixedOrientationLandscape(activityOrientation); - } - - /** * Calculates the desired initial bounds for applications in desktop windowing. This is done as * a scale of the screen bounds. */ - private static @NonNull Size calculateIdealSize(@NonNull Rect screenBounds, float scale) { + @NonNull + private static Size calculateIdealSize(@NonNull Rect screenBounds, float scale) { final int width = (int) (screenBounds.width() * scale); final int height = (int) (screenBounds.height() * scale); return new Size(width, height); @@ -299,7 +267,8 @@ public final class DesktopModeBoundsCalculator { /** * Adjusts bounds to be positioned in the middle of the screen. */ - private static @NonNull Rect centerInScreen(@NonNull Size desiredSize, + @NonNull + private static Rect centerInScreen(@NonNull Size desiredSize, @NonNull Rect screenBounds) { // TODO(b/325240051): Position apps with bottom heavy offset final int heightOffset = (screenBounds.height() - desiredSize.getHeight()) / 2; @@ -309,57 +278,4 @@ public final class DesktopModeBoundsCalculator { resultBounds.offset(screenBounds.left + widthOffset, screenBounds.top + heightOffset); return resultBounds; } - - private static float getFixedOrientationLetterboxAspectRatio(@NonNull ActivityRecord activity, - @NonNull Task task) { - return activity.shouldCreateCompatDisplayInsets() - ? getDefaultMinAspectRatioForUnresizableApps(activity, task) - : activity.mAppCompatController.getAppCompatAspectRatioOverrides() - .getDefaultMinAspectRatio(); - } - - private static float getDefaultMinAspectRatioForUnresizableApps( - @NonNull ActivityRecord activity, - @NonNull Task task) { - final AppCompatAspectRatioOverrides appCompatAspectRatioOverrides = - activity.mAppCompatController.getAppCompatAspectRatioOverrides(); - if (appCompatAspectRatioOverrides.isSplitScreenAspectRatioForUnresizableAppsEnabled()) { - // Default letterbox aspect ratio for unresizable apps. - return getSplitScreenAspectRatio(activity, task); - } - - if (appCompatAspectRatioOverrides.getDefaultMinAspectRatioForUnresizableAppsFromConfig() - > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { - return appCompatAspectRatioOverrides - .getDefaultMinAspectRatioForUnresizableAppsFromConfig(); - } - - return appCompatAspectRatioOverrides.getDefaultMinAspectRatio(); - } - - /** - * Calculates the aspect ratio of the available display area when an app enters split-screen on - * a given device, taking into account any dividers and insets. - */ - private static float getSplitScreenAspectRatio(@NonNull ActivityRecord activity, - @NonNull Task task) { - final int dividerWindowWidth = - activity.mWmService.mContext.getResources().getDimensionPixelSize( - R.dimen.docked_stack_divider_thickness); - final int dividerInsets = - activity.mWmService.mContext.getResources().getDimensionPixelSize( - R.dimen.docked_stack_divider_insets); - final int dividerSize = dividerWindowWidth - dividerInsets * 2; - final Rect bounds = new Rect(0, 0, - task.mDisplayContent.getDisplayInfo().appWidth, - task.mDisplayContent.getDisplayInfo().appHeight); - if (bounds.width() >= bounds.height()) { - bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); - bounds.right = bounds.centerX(); - } else { - bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); - bounds.bottom = bounds.centerY(); - } - return computeAspectRatio(bounds); - } } diff --git a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java index 3dba57f8c4cd..37e4449a2dd0 100644 --- a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java +++ b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java @@ -55,10 +55,11 @@ public class DimmerAnimationHelper { Change() {} - Change(@NonNull Change other) { + void copyFrom(@NonNull Change other) { mAlpha = other.mAlpha; mBlurRadius = other.mBlurRadius; mDimmingContainer = other.mDimmingContainer; + mGeometryParent = other.mGeometryParent; mRelativeLayer = other.mRelativeLayer; } @@ -83,8 +84,8 @@ public class DimmerAnimationHelper { } } - private Change mCurrentProperties = new Change(); - private Change mRequestedProperties = new Change(); + private final Change mCurrentProperties = new Change(); + private final Change mRequestedProperties = new Change(); private AnimationSpec mAlphaAnimationSpec; private final AnimationAdapterFactory mAnimationAdapterFactory; @@ -128,7 +129,7 @@ public class DimmerAnimationHelper { + "call adjustRelativeLayer?"); return; } - if (mRequestedProperties.mDimmingContainer.mSurfaceControl == null) { + if (mRequestedProperties.mDimmingContainer.getSurfaceControl() == null) { Log.w(TAG, "container " + mRequestedProperties.mDimmingContainer + "does not have a surface"); dim.remove(t); @@ -154,35 +155,35 @@ public class DimmerAnimationHelper { "%s skipping animation and directly setting alpha=%f, blur=%d", dim, mRequestedProperties.mAlpha, mRequestedProperties.mBlurRadius); - setAlphaBlur(dim.mDimSurface, mRequestedProperties.mAlpha, - mRequestedProperties.mBlurRadius, t); + mCurrentProperties.copyFrom(mRequestedProperties); + setCurrentAlphaBlur(dim.mDimSurface, t); dim.mSkipAnimation = false; } else { - startAnimation(t, dim); + Change startProperties = mCurrentProperties; + mCurrentProperties.copyFrom(mRequestedProperties); + startAnimation(t, dim, startProperties, mRequestedProperties); } - } else if (!dim.isDimming()) { // We are not dimming, so we tried the exit animation but the alpha is already 0, // therefore, let's just remove this surface dim.remove(t); } - mCurrentProperties = new Change(mRequestedProperties); } private void startAnimation( - @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim) { + @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim, + @NonNull Change from, @NonNull Change to) { ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim); - mAlphaAnimationSpec = getRequestedAnimationSpec(); + mAlphaAnimationSpec = getRequestedAnimationSpec(from, to); mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec, dim.mHostContainer.mWmService.mSurfaceAnimationRunner); - float targetAlpha = mRequestedProperties.mAlpha; - int targetBlur = mRequestedProperties.mBlurRadius; + float targetAlpha = to.mAlpha; mLocalAnimationAdapter.startAnimation(dim.mDimSurface, t, ANIMATION_TYPE_DIMMER, /* finishCallback */ (type, animator) -> { synchronized (dim.mHostContainer.mWmService.mGlobalLock) { - setAlphaBlur(dim.mDimSurface, targetAlpha, targetBlur, t); + setCurrentAlphaBlur(dim.mDimSurface, t); if (targetAlpha == 0f && !dim.isDimming()) { dim.remove(t); } @@ -207,15 +208,15 @@ public class DimmerAnimationHelper { } @NonNull - private AnimationSpec getRequestedAnimationSpec() { - final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f); - final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0); - long duration = (long) (getDimDuration(mRequestedProperties.mDimmingContainer) - * Math.abs(mRequestedProperties.mAlpha - startAlpha)); + private static AnimationSpec getRequestedAnimationSpec(Change from, Change to) { + final float startAlpha = Math.max(from.mAlpha, 0f); + final int startBlur = Math.max(from.mBlurRadius, 0); + long duration = (long) (getDimDuration(to.mDimmingContainer) + * Math.abs(to.mAlpha - startAlpha)); final AnimationSpec spec = new AnimationSpec( - new AnimationSpec.AnimationExtremes<>(startAlpha, mRequestedProperties.mAlpha), - new AnimationSpec.AnimationExtremes<>(startBlur, mRequestedProperties.mBlurRadius), + new AnimationSpec.AnimationExtremes<>(startAlpha, to.mAlpha), + new AnimationSpec.AnimationExtremes<>(startBlur, to.mBlurRadius), duration ); ProtoLog.v(WM_DEBUG_DIMMER, "Dim animation requested: %s", spec); @@ -225,7 +226,7 @@ public class DimmerAnimationHelper { /** * Change the geometry and relative parent of this dim layer */ - void reparent(@NonNull SurfaceControl dimLayer, + static void reparent(@NonNull SurfaceControl dimLayer, @Nullable SurfaceControl newGeometryParent, @NonNull SurfaceControl relativeParent, int relativePosition, @@ -240,17 +241,16 @@ public class DimmerAnimationHelper { } } - void setAlphaBlur(@NonNull SurfaceControl sc, float alpha, int blur, - @NonNull SurfaceControl.Transaction t) { + void setCurrentAlphaBlur(@NonNull SurfaceControl sc, @NonNull SurfaceControl.Transaction t) { try { - t.setAlpha(sc, alpha); - t.setBackgroundBlurRadius(sc, blur); + t.setAlpha(sc, mCurrentProperties.mAlpha); + t.setBackgroundBlurRadius(sc, mCurrentProperties.mBlurRadius); } catch (NullPointerException e) { Log.w(TAG , "Tried to change look of dim " + sc + " after remove", e); } } - private long getDimDuration(@NonNull WindowContainer<?> container) { + private static long getDimDuration(@NonNull WindowContainer<?> container) { // Use the same duration as the animation on the WindowContainer AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation(); final float durationScale = container.mWmService.getTransitionAnimationScaleLocked(); diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 86f69cd3a802..ca5485e7c570 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -356,7 +356,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, int logLevel) { - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index fcc6b11d46c5..648f6bda7f98 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -45,7 +45,6 @@ import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Display.INVALID_DISPLAY; -import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static android.view.Display.STATE_UNKNOWN; import static android.view.Display.isSuspendedState; import static android.view.InsetsSource.ID_IME; @@ -80,6 +79,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_OPEN; @@ -3565,9 +3565,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { // Critical log level logs only visible elements to mitigate performance overheard - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } @@ -6556,7 +6556,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @VisibleForTesting boolean shouldDestroyContentOnRemove() { - return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; + return getRemoveContentMode() == REMOVE_CONTENT_MODE_DESTROY; + } + + @WindowManager.RemoveContentMode + int getRemoveContentMode() { + return mWmService.mDisplayWindowSettings.getRemoveContentModeLocked(this); } boolean shouldSleep() { diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java index 762180b1b778..27d97677bb13 100644 --- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java @@ -76,6 +76,11 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp @ScreenOrientation private int mLastReportedOrientation = SCREEN_ORIENTATION_UNSET; + /** + * Value toggled on {@link #start()} to {@code true} and on {@link #dispose()} to {@code false}. + */ + private boolean mIsRunning; + DisplayRotationCompatPolicy(@NonNull DisplayContent displayContent, @NonNull CameraStateMonitor cameraStateMonitor, @NonNull ActivityRefresher activityRefresher) { @@ -90,12 +95,19 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp void start() { mCameraStateMonitor.addCameraStateListener(this); mActivityRefresher.addEvaluator(this); + mIsRunning = true; } /** Releases camera state listener. */ void dispose() { mCameraStateMonitor.removeCameraStateListener(this); mActivityRefresher.removeEvaluator(this); + mIsRunning = false; + } + + @VisibleForTesting + boolean isRunning() { + return mIsRunning; } /** diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 2f0ee171b5ba..f40f26179f85 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; @@ -183,7 +184,7 @@ class DisplayWindowSettings { final DisplayInfo displayInfo = dc.getDisplayInfo(); final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); if (settings.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) { - if (dc.isPrivate()) { + if (dc.isPrivate() || dc.getDisplay().getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT) { // For private displays by default content is destroyed on removal. return REMOVE_CONTENT_MODE_DESTROY; } diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java index c66d6596226a..169a76fe3afd 100644 --- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java +++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java @@ -403,7 +403,7 @@ class EmbeddedWindowController { @Override public void dumpProto(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { final long token = proto.start(fieldId); final long token2 = proto.start(IDENTIFIER); diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 3a5f9b7dd4fc..6b916ef04e38 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -726,7 +726,7 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { } @Override - void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) { + void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTracingLogLevel int logLevel) { final long token = proto.start(fieldId); super.dumpDebug(proto, INSETS_SOURCE_PROVIDER, logLevel); final WindowState imeRequesterWindow = diff --git a/services/core/java/com/android/server/wm/InputTarget.java b/services/core/java/com/android/server/wm/InputTarget.java index baf0db2e0b7e..0c0b794182e7 100644 --- a/services/core/java/com/android/server/wm/InputTarget.java +++ b/services/core/java/com/android/server/wm/InputTarget.java @@ -65,6 +65,6 @@ interface InputTarget { InsetsControlTarget getImeControlTarget(); void dumpProto(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel); + @WindowTracingLogLevel int logLevel); } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index f5c92f60b26a..b66b8bc2115b 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -725,7 +725,7 @@ class InsetsSourceProvider { } } - void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) { + void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTracingLogLevel int logLevel) { final long token = proto.start(fieldId); mSource.dumpDebug(proto, SOURCE); mTmpRect.dumpDebug(proto, FRAME); diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 9c2a8def4d56..098a691e0490 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -462,7 +462,7 @@ class InsetsStateController { } } - void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) { + void dumpDebug(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) { for (int i = mProviders.size() - 1; i >= 0; i--) { final InsetsSourceProvider provider = mProviders.valueAt(i); provider.dumpDebug(proto, diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java deleted file mode 100644 index 0e8291ee9492..000000000000 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ /dev/null @@ -1,132 +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.server.wm; - -import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; -import static com.android.server.wm.AppCompatConfiguration.letterboxBackgroundTypeToString; - -import android.annotation.NonNull; - -import java.io.PrintWriter; - -/** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */ -// TODO(b/185262487): Improve test coverage of this class. Parts of it are tested in -// SizeCompatTests and LetterboxTests but not all. -final class LetterboxUiController { - - private final AppCompatConfiguration mAppCompatConfiguration; - - private final ActivityRecord mActivityRecord; - - // TODO(b/356385137): Remove these we added to make dependencies temporarily explicit. - @NonNull - private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides; - @NonNull - private final AppCompatLetterboxPolicy mAppCompatLetterboxPolicy; - @NonNull - private final AppCompatLetterboxOverrides mAppCompatLetterboxOverrides; - - LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) { - mAppCompatConfiguration = wmService.mAppCompatConfiguration; - // Given activityRecord may not be fully constructed since LetterboxUiController - // is created in its constructor. It shouldn't be used in this constructor but it's safe - // to use it after since controller is only used in ActivityRecord. - mActivityRecord = activityRecord; - // TODO(b/356385137): Remove these we added to make dependencies temporarily explicit. - mAppCompatReachabilityOverrides = mActivityRecord.mAppCompatController - .getAppCompatReachabilityOverrides(); - mAppCompatLetterboxPolicy = mActivityRecord.mAppCompatController - .getAppCompatLetterboxPolicy(); - mAppCompatLetterboxOverrides = mActivityRecord.mAppCompatController - .getAppCompatLetterboxOverrides(); - } - - void dump(PrintWriter pw, String prefix) { - final WindowState mainWin = mActivityRecord.findMainWindow(); - if (mainWin == null) { - return; - } - - pw.println(prefix + "isTransparentPolicyRunning=" - + mActivityRecord.mAppCompatController.getTransparentPolicy().isRunning()); - - boolean areBoundsLetterboxed = mainWin.areAppWindowBoundsLetterboxed(); - pw.println(prefix + "areBoundsLetterboxed=" + areBoundsLetterboxed); - if (!areBoundsLetterboxed) { - return; - } - - pw.println(prefix + " letterboxReason=" - + AppCompatUtils.getLetterboxReasonString(mActivityRecord, mainWin)); - pw.println(prefix + " activityAspectRatio=" - + AppCompatUtils.computeAspectRatio(mActivityRecord.getBounds())); - - boolean shouldShowLetterboxUi = mAppCompatLetterboxPolicy.shouldShowLetterboxUi(mainWin); - pw.println(prefix + "shouldShowLetterboxUi=" + shouldShowLetterboxUi); - - if (!shouldShowLetterboxUi) { - return; - } - pw.println(prefix + " isVerticalThinLetterboxed=" - + mAppCompatReachabilityOverrides.isVerticalThinLetterboxed()); - pw.println(prefix + " isHorizontalThinLetterboxed=" - + mAppCompatReachabilityOverrides.isHorizontalThinLetterboxed()); - pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString( - mAppCompatLetterboxOverrides.getLetterboxBackgroundColor().toArgb())); - pw.println(prefix + " letterboxBackgroundType=" - + letterboxBackgroundTypeToString( - mAppCompatConfiguration.getLetterboxBackgroundType())); - pw.println(prefix + " letterboxCornerRadius=" - + mAppCompatLetterboxPolicy.getRoundedCornersRadius(mainWin)); - if (mAppCompatConfiguration.getLetterboxBackgroundType() - == LETTERBOX_BACKGROUND_WALLPAPER) { - pw.println(prefix + " isLetterboxWallpaperBlurSupported=" - + mAppCompatLetterboxOverrides.isLetterboxWallpaperBlurSupported()); - pw.println(prefix + " letterboxBackgroundWallpaperDarkScrimAlpha=" - + mAppCompatLetterboxOverrides.getLetterboxWallpaperDarkScrimAlpha()); - pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius=" - + mAppCompatLetterboxOverrides.getLetterboxWallpaperBlurRadiusPx()); - } - final AppCompatReachabilityOverrides reachabilityOverrides = mActivityRecord - .mAppCompatController.getAppCompatReachabilityOverrides(); - pw.println(prefix + " isHorizontalReachabilityEnabled=" - + reachabilityOverrides.isHorizontalReachabilityEnabled()); - pw.println(prefix + " isVerticalReachabilityEnabled=" - + reachabilityOverrides.isVerticalReachabilityEnabled()); - pw.println(prefix + " letterboxHorizontalPositionMultiplier=" - + mAppCompatReachabilityOverrides.getHorizontalPositionMultiplier(mActivityRecord - .getParent().getConfiguration())); - pw.println(prefix + " letterboxVerticalPositionMultiplier=" - + mAppCompatReachabilityOverrides.getVerticalPositionMultiplier(mActivityRecord - .getParent().getConfiguration())); - pw.println(prefix + " letterboxPositionForHorizontalReachability=" - + AppCompatConfiguration.letterboxHorizontalReachabilityPositionToString( - mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(false))); - pw.println(prefix + " letterboxPositionForVerticalReachability=" - + AppCompatConfiguration.letterboxVerticalReachabilityPositionToString( - mAppCompatConfiguration.getLetterboxPositionForVerticalReachability(false))); - pw.println(prefix + " fixedOrientationLetterboxAspectRatio=" - + mAppCompatConfiguration.getFixedOrientationLetterboxAspectRatio()); - pw.println(prefix + " defaultMinAspectRatioForUnresizableApps=" - + mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps()); - pw.println(prefix + " isSplitScreenAspectRatioForUnresizableAppsEnabled=" - + mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled()); - pw.println(prefix + " isDisplayAspectRatioEnabledForFixedOrientationLetterbox=" - + mAppCompatConfiguration - .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()); - } -} diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index 60454fc5d7c6..781023c688c3 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -30,3 +30,4 @@ per-file ActivityCallerState.java = file:/core/java/android/app/COMPONENT_CALLER # Files related to tracing per-file *TransitionTracer.java = file:platform/development:/tools/winscope/OWNERS +per-file *WindowTracing* = file:platform/development:/tools/winscope/OWNERS diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index bded98c6c07f..4ca4730923f5 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1002,6 +1002,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // complete configuration. continue; } + win.updateSurfacePositionIfNeeded(); win.reportResized(); mWmService.mResizingWindows.remove(i); } @@ -1189,8 +1190,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + @WindowTracingLogLevel int logLevel) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } @@ -1633,7 +1634,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Only resume home activity if isn't finishing. if (r != null && !r.finishing) { r.moveFocusableActivityToTop(myReason); - return resumeFocusedTasksTopActivities(r.getRootTask(), prev, null); + return resumeFocusedTasksTopActivities(r.getRootTask(), prev); } int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId()); return startHomeOnTaskDisplayArea(userId, myReason, taskDisplayArea, @@ -2202,7 +2203,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // During recents animations, the original task is "occluded" by launcher but // it wasn't paused (due to transient-launch). If we reparent to the (top) task // now, it will take focus briefly which confuses the RecentTasks tracker. - rootTask.setWindowingMode(WINDOWING_MODE_PINNED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); } // Temporarily disable focus when reparenting to avoid intermediate focus change // (because the task is on top and the activity is resumed), which could cause the @@ -2235,7 +2236,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing // legacy transit. - rootTask.setWindowingMode(WINDOWING_MODE_PINNED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); if (isPip2ExperimentEnabled() && bounds != null) { // set the final pip bounds in advance if pip2 is enabled rootTask.setBounds(bounds); @@ -2470,12 +2471,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } boolean resumeFocusedTasksTopActivities() { - return resumeFocusedTasksTopActivities(null, null, null); + return resumeFocusedTasksTopActivities(null, null, null, false /* deferPause */); } boolean resumeFocusedTasksTopActivities( - Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) { - return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions, + Task targetRootTask, ActivityRecord target) { + return resumeFocusedTasksTopActivities(targetRootTask, target, null /* targetOptions */, false /* deferPause */); } @@ -2527,7 +2528,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // activity is started and resumed, and no recursion occurs. final Task focusedRoot = display.getFocusedRootTask(); if (focusedRoot != null) { - result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions); + result |= focusedRoot.resumeTopActivityUncheckedLocked( + target, targetOptions, false /* skipPause */); } else if (targetRootTask == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); @@ -2632,7 +2634,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // process the keyguard going away, which can happen before the sleep // token is released. As a result, it is important we resume the // activity here. - rootTask.resumeTopActivityUncheckedLocked(null, null); + rootTask.resumeTopActivityUncheckedLocked(); } // The visibility update must not be called before resuming the top, so the // display orientation can be updated first if needed. Otherwise there may @@ -3426,26 +3428,30 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allResumedActivitiesIdle() { for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { - // TODO(b/117135575): Check resumed activities on all visible root tasks. final DisplayContent display = getChildAt(displayNdx); if (display.isSleeping()) { // No resumed activities while display is sleeping. continue; } - // If the focused root task is not null or not empty, there should have some activities - // resuming or resumed. Make sure these activities are idle. - final Task rootTask = display.getFocusedRootTask(); - if (rootTask == null || !rootTask.hasActivity()) { - continue; - } - final ActivityRecord resumedActivity = rootTask.getTopResumedActivity(); - if (resumedActivity == null || !resumedActivity.idle) { - ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: rootTask=%d %s " - + "not idle", rootTask.getRootTaskId(), resumedActivity); + final boolean foundNotIdle = display.forAllLeafTaskFragments(tf -> { + if (!tf.isVisibleRequested()) { + return false; + } + // Note that only activities that will be resumed can report idle. + final ActivityRecord r = tf.topRunningActivity(); + if (r != null && !r.idle && (r.isState(RESUMED) + // Its process is not attached yet and it may resume later. + || (r.app == null && r.isFocusable()))) { + ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", r); + return true; + } + return false; + }); + if (foundNotIdle) { return false; } - if (mTransitionController.isTransientLaunch(resumedActivity)) { + if (mTransitionController.hasTransientLaunch(display)) { // Not idle if the transient transition animation is running. return false; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 12e91adef9c5..efa9c5345f77 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4540,7 +4540,8 @@ class Task extends TaskFragment { reparent(parent, MAX_VALUE); } - setWindowingMode(mMultiWindowRestoreWindowingMode); + // mMultiWindowRestoreWindowingMode is INVALID for non-root tasks + setRootTaskWindowingMode(mMultiWindowRestoreWindowingMode); } @Override @@ -4553,18 +4554,30 @@ class Task extends TaskFragment { return; } - setWindowingMode(windowingMode, false /* creating */); + setWindowingModeInner(windowingMode, false /* creating */); } /** - * Specialization of {@link #setWindowingMode(int)} for this subclass. + * Version of {@link #setWindowingMode(int)} for root tasks. * * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the * previous non-transient mode if this root task is currently in a transient mode. + */ + public void setRootTaskWindowingMode(int preferredWindowingMode) { + if (!isRootTask()) { + Slog.wtf(TAG, "Trying to set root-task windowing-mode on a non-root-task: " + this, + new Throwable()); + super.setWindowingMode(preferredWindowingMode); + return; + } + setWindowingModeInner(preferredWindowingMode, false /* creating */); + } + + /** * @param creating {@code true} if this is being run during task construction. */ - void setWindowingMode(int preferredWindowingMode, boolean creating) { + private void setWindowingModeInner(int preferredWindowingMode, boolean creating) { final TaskDisplayArea taskDisplayArea = getDisplayArea(); if (taskDisplayArea == null) { Slog.d(TAG, "taskDisplayArea is null, bail early"); @@ -4657,6 +4670,9 @@ class Task extends TaskFragment { mTransitionController.collect(topActivity); final Task lastParentBeforePip = topActivity.getLastParentBeforePip(); + // Reset the activity windowing mode to match the parent. + topActivity.getRequestedOverrideConfiguration() + .windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED); topActivity.reparent(lastParentBeforePip, lastParentBeforePip.getChildCount() /* top */, "movePinnedActivityToOriginalTask"); @@ -4689,6 +4705,15 @@ class Task extends TaskFragment { // it does not follow the ActivityStarter path. if (topActivity.shouldBeVisible()) { mAtmService.resumeAppSwitches(); + // In pip1, when expanding pip to full-screen, the "behind" task is not + // actually becoming invisible since task windowing mode is pinned. + if (!isPip2ExperimentEnabled) { + final ActivityRecord ar = mAtmService.mLastResumedActivity; + if (ar != null && ar.getTask() != null) { + mAtmService.takeTaskSnapshot(ar.getTask().mTaskId, + true /* updateCache */); + } + } } } else if (isPip2ExperimentEnabled) { super.setWindowingMode(windowingMode); @@ -4740,7 +4765,7 @@ class Task extends TaskFragment { } } if (isAttached()) { - setWindowingMode(WINDOWING_MODE_UNDEFINED); + setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); moveTaskToBackInner(this, null /* transition */); } if (top.isAttached()) { @@ -5086,10 +5111,10 @@ class Task extends TaskFragment { return someActivityResumed; } - /** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */ @GuardedBy("mService") - boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { - return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */); + boolean resumeTopActivityUncheckedLocked() { + return resumeTopActivityUncheckedLocked(null /* prev */, null /* options */, + false /* skipPause */); } @GuardedBy("mService") @@ -5138,8 +5163,7 @@ class Task extends TaskFragment { // Try to move focus to the next visible root task with a running activity if this // root task is not covering the entire screen or is on a secondary display with // no home root task. - return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask, - prev, null /* targetOptions */); + return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask, prev); } } @@ -5661,8 +5685,10 @@ class Task extends TaskFragment { if (noAnimation) { mDisplayContent.prepareAppTransition(TRANSIT_NONE); mTaskSupervisor.mNoAnimActivities.add(top); - mTransitionController.collect(top); - mTransitionController.setNoAnimation(top); + if (mTransitionController.isShellTransitionsEnabled()) { + mTransitionController.collect(top); + mTransitionController.setNoAnimation(top); + } ActivityOptions.abort(options); } else { updateTransitLocked(TRANSIT_TO_FRONT, options); @@ -6002,7 +6028,7 @@ class Task extends TaskFragment { } final Task task = getBottomMostTask(); - setWindowingMode(WINDOWING_MODE_UNDEFINED); + setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); // Task could have been removed from the hierarchy due to windowing mode change // where its only child is reparented back to their original parent task. @@ -6245,8 +6271,8 @@ class Task extends TaskFragment { @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + @WindowTracingLogLevel int logLevel) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } @@ -6674,7 +6700,7 @@ class Task extends TaskFragment { // Set windowing mode after attached to display area or it abort silently. if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { - task.setWindowingMode(mWindowingMode, true /* creating */); + task.setWindowingModeInner(mWindowingMode, true /* creating */); } return task; } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index dba1c364b89b..d9e88e1e460a 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -923,7 +923,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { if (windowingMode != WINDOWING_MODE_UNDEFINED && candidateTask.isRootTask() && candidateTask.getWindowingMode() != windowingMode) { candidateTask.mTransitionController.collect(candidateTask); - candidateTask.setWindowingMode(windowingMode); + candidateTask.setRootTaskWindowingMode(windowingMode); } return candidateTask.getRootTask(); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 2ee157f42615..2fbabc51c534 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1780,11 +1780,6 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (resuming != null) { // We do not want to trigger auto-PiP upon launch of a translucent activity. final boolean resumingOccludesParent = resuming.occludesParent(); - // Resuming the new resume activity only if the previous activity can't go into Pip - // since we want to give Pip activities a chance to enter Pip before resuming the - // next activity. - final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState( - "shouldAutoPipWhilePausing", userLeaving); if (ActivityTaskManagerService.isPip2ExperimentEnabled()) { // If a new task is being launched, then mark the existing top activity as @@ -1794,6 +1789,12 @@ class TaskFragment extends WindowContainer<WindowContainer> { Task.enableEnterPipOnTaskSwitch(prev, resuming.getTask(), resuming, resuming.getOptions()); } + + // Resuming the new resume activity only if the previous activity can't go into Pip + // since we want to give Pip activities a chance to enter Pip before resuming the + // next activity. + final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState( + "shouldAutoPipWhilePausing", userLeaving); if (prev.supportsEnterPipOnTaskSwitch && userLeaving && resumingOccludesParent && lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) { @@ -1927,7 +1928,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { prev.setState(STOPPING, "completePausedLocked"); } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) { // Clear out any deferred client hide we might currently have. - prev.setDeferHidingClient(false); + prev.clearDeferHidingClient(); // If we were visible then resumeTopActivities will release resources before // stopping. prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */, @@ -1948,8 +1949,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (resumeNext) { final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) { - mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev, - null /* targetOptions */); + mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev); } else { // checkReadyForSleep(); final ActivityRecord top = @@ -3335,8 +3335,8 @@ class TaskFragment extends WindowContainer<WindowContainer> { @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + @WindowTracingLogLevel int logLevel) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 9ee1fbe91d83..de2e4f5474c4 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -390,7 +390,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { t.mTaskAppearedSent = false; } if (removeFromSystem) { - mService.removeTask(t.mTaskId); + mService.removeTask(t); } return taskAppearedSent; } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 486a61b7aef6..b768bb155563 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -420,6 +420,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { updateTransientFlags(mChanges.valueAt(i)); } } + + // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. + // Also interpret HOME transient launch as recents + if (activity.isActivityTypeHomeOrRecents()) { + addFlag(TRANSIT_FLAG_IS_RECENTS); + // When starting recents animation, we assume the recents activity is behind the app + // task and should not affect system bar appearance, + // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing + // the gesture threshold. + activity.getTask().setCanAffectSystemUiFlags(false); + } + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Transition %d: Set %s as " + "transient-launch", mSyncId, activity); } @@ -1721,6 +1733,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { transaction.addTransactionCompletedListener(Runnable::run, (stats) -> listener.run()); } + mTransactionCompletedListeners = null; } // Fall-back to the default display if there isn't one participating. @@ -1763,6 +1776,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (mPriorVisibilityMightBeDirty) { updatePriorVisibility(); } + // Resolve the animating targets from the participants. mTargets = calculateTargets(mParticipants, mChanges); @@ -1840,8 +1854,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // already been reset by the original hiding-transition's finishTransaction (we can't // show in the finishTransaction because by then the activity doesn't hide until // surface placement). - for (WindowContainer p = ar.getParent(); p != null && !containsChangeFor(p, mTargets); - p = p.getParent()) { + for (WindowContainer p = ar.getParent(); + p != null && !containsChangeFor(p, mTargets) && !p.isOrganized(); + p = p.getParent()) { if (p.getSurfaceControl() != null) { transaction.show(p.getSurfaceControl()); } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 67d7b37396c0..ef25eda1d876 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; -import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; import static android.view.WindowManager.TRANSIT_NONE; import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY; @@ -53,8 +52,8 @@ import android.window.WindowContainerTransaction; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.ProtoLog; +import com.android.internal.protolog.ProtoLogGroup; import com.android.server.FgThread; import com.android.window.flags.Flags; @@ -1311,23 +1310,6 @@ class TransitionController { void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelowTask) { if (mCollectingTransition == null) return; mCollectingTransition.setTransientLaunch(activity, restoreBelowTask); - - // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. - // Also interpret HOME transient launch as recents - if (activity.isActivityTypeHomeOrRecents()) { - mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS); - // When starting recents animation, we assume the recents activity is behind the app - // task and should not affect system bar appearance, - // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing - // the gesture threshold. - activity.getTask().setCanAffectSystemUiFlags(false); - } - } - - /** @see Transition#setCanPipOnFinish */ - void setCanPipOnFinish(boolean canPipOnFinish) { - if (mCollectingTransition == null) return; - mCollectingTransition.setCanPipOnFinish(canPipOnFinish); } void legacyDetachNavigationBarFromApp(@NonNull IBinder token) { @@ -1459,7 +1441,7 @@ class TransitionController { * * WARNING: ONLY use this if the transition absolutely cannot be deferred! */ - @NonNull + @Nullable Transition createAndStartCollecting(int type) { if (mTransitionPlayers.isEmpty()) { return null; diff --git a/services/core/java/com/android/server/wm/TransparentPolicy.java b/services/core/java/com/android/server/wm/TransparentPolicy.java index 39b2635eb8ac..36bc84635e94 100644 --- a/services/core/java/com/android/server/wm/TransparentPolicy.java +++ b/services/core/java/com/android/server/wm/TransparentPolicy.java @@ -31,6 +31,7 @@ import android.annotation.Nullable; import android.content.res.Configuration; import android.graphics.Rect; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -188,6 +189,10 @@ class TransparentPolicy { return mTransparentPolicyState.findOpaqueNotFinishingActivityBelow(); } + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + pw.println(prefix + "isTransparentPolicyRunning=" + isRunning()); + } + // We evaluate the case when the policy should not be applied. private boolean shouldSkipTransparentPolicy(@Nullable ActivityRecord opaqueActivity) { if (opaqueActivity == null || opaqueActivity.isEmbedded()) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 64f9c012ea28..9ae881bc8745 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1611,8 +1611,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * * @param orientation the specified orientation. */ - void setOrientation(@ScreenOrientation int orientation) { - setOrientation(orientation, null /* requestingContainer */); + protected void setOrientation(@ScreenOrientation int orientation) { + setOrientation(orientation, null /* requesting */); } /** @@ -2784,9 +2784,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< @CallSuper @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { boolean isVisible = isVisible(); - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible) { return; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5749272376ac..bdb1d43faf79 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -6858,7 +6858,7 @@ public class WindowManagerService extends IWindowManager.Stub * @param proto Stream to write the WindowContainer object to. * @param logLevel Determines the amount of data to be written to the Protobuf. */ - void dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) { + void dumpDebugLocked(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) { mPolicy.dumpDebug(proto, POLICY); mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel); final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent(); @@ -7217,7 +7217,7 @@ public class WindowManagerService extends IWindowManager.Stub if (useProto) { final ProtoOutputStream proto = new ProtoOutputStream(fd); synchronized (mGlobalLock) { - dumpDebugLocked(proto, WindowTraceLogLevel.ALL); + dumpDebugLocked(proto, WindowTracingLogLevel.ALL); } proto.flush(); return; @@ -7656,7 +7656,7 @@ public class WindowManagerService extends IWindowManager.Stub displayId); return REMOVE_CONTENT_MODE_UNDEFINED; } - return mDisplayWindowSettings.getRemoveContentModeLocked(displayContent); + return displayContent.getRemoveContentMode(); } } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index c6d0b729cd5a..9d40b16c37ae 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -322,11 +322,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // This is a direct call from shell, so the entire transition lifecycle is // contained in the provided transaction if provided. Thus, we can setReady // immediately after apply. - final Transition.ReadyCondition wctApplied = - new Transition.ReadyCondition("start WCT applied"); final boolean needsSetReady = t != null; final Transition nextTransition = new Transition(type, 0 /* flags */, mTransitionController, mService.mWindowManager.mSyncEngine); + final Transition.ReadyCondition wctApplied = + new Transition.ReadyCondition("start WCT applied"); nextTransition.mReadyTracker.add(wctApplied); nextTransition.calcParallelCollectType(wct); mTransitionController.startCollectOrQueue(nextTransition, @@ -342,15 +342,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub }); return nextTransition.getToken(); } - // Currently, application of wct can span multiple looper loops (ie. - // waitAsyncStart), so add a condition to ensure that it finishes applying. - final Transition.ReadyCondition wctApplied; - if (t != null) { - wctApplied = new Transition.ReadyCondition("start WCT applied"); - transition.mReadyTracker.add(wctApplied); - } else { - wctApplied = null; - } // The transition already started collecting before sending a request to shell, // so just start here. if (!transition.isCollecting() && !transition.isForcePlaying()) { @@ -358,11 +349,17 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + " means Shell took too long to respond to a request. WM State may be" + " incorrect now, please file a bug"); applyTransaction(wct, -1 /*syncId*/, null /*transition*/, caller); - if (wctApplied != null) { - wctApplied.meet(); - } return transition.getToken(); } + // Currently, application of wct can span multiple looper loops (ie. + // waitAsyncStart), so add a condition to ensure that it finishes applying. + final Transition.ReadyCondition wctApplied; + if (t != null) { + wctApplied = new Transition.ReadyCondition("start WCT applied"); + transition.mReadyTracker.add(wctApplied); + } else { + wctApplied = null; + } transition.mLogger.mStartWCT = wct; if (transition.shouldApplyOnDisplayThread()) { mService.mH.post(() -> { @@ -851,7 +848,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } final int prevMode = container.getRequestedOverrideWindowingMode(); - container.setWindowingMode(windowingMode); + if (container.asTask() != null && container.asTask().isRootTask()) { + container.asTask().setRootTaskWindowingMode(windowingMode); + } else { + container.setWindowingMode(windowingMode); + } if (prevMode != container.getWindowingMode()) { // The activity in the container may become focusable or non-focusable due to // windowing modes changes (such as entering or leaving pinned windowing mode), diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b6e8977d2e45..4568f2eac95c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4072,9 +4072,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @CallSuper @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { boolean isVisible = isVisible(); - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible) { return; } @@ -5333,6 +5333,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP super.prepareSurfaces(); } + void updateSurfacePositionIfNeeded() { + if (mWindowFrames.mRelFrame.top == mWindowFrames.mLastRelFrame.top + && mWindowFrames.mRelFrame.left == mWindowFrames.mLastRelFrame.left) { + return; + } + updateSurfacePosition(getSyncTransaction()); + } + @Override @VisibleForTesting void updateSurfacePosition(Transaction t) { @@ -6140,7 +6148,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override public void dumpProto(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { + @WindowTracingLogLevel int logLevel) { dumpDebug(proto, fieldId, logLevel); } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 11ef2cde65a9..67bd5cb833ae 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -698,8 +698,8 @@ class WindowToken extends WindowContainer<WindowState> { @CallSuper @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, - @WindowTraceLogLevel int logLevel) { - if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + @WindowTracingLogLevel int logLevel) { + if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { return; } diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java index 04d5c03e64a6..fe267261b9e6 100644 --- a/services/core/java/com/android/server/wm/WindowTracing.java +++ b/services/core/java/com/android/server/wm/WindowTracing.java @@ -112,7 +112,7 @@ abstract class WindowTracing { saveForBugreportInternal(pw); } - abstract void setLogLevel(@WindowTraceLogLevel int logLevel, PrintWriter pw); + abstract void setLogLevel(@WindowTracingLogLevel int logLevel, PrintWriter pw); abstract void setLogFrequency(boolean onFrame, PrintWriter pw); abstract void setBufferCapacity(int capacity, PrintWriter pw); abstract boolean isEnabled(); @@ -158,7 +158,7 @@ abstract class WindowTracing { * @param where Logging point descriptor * @param elapsedRealtimeNanos Timestamp */ - protected void dumpToProto(ProtoOutputStream os, @WindowTraceLogLevel int logLevel, + protected void dumpToProto(ProtoOutputStream os, @WindowTracingLogLevel int logLevel, String where, long elapsedRealtimeNanos) { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked"); try { diff --git a/services/core/java/com/android/server/wm/WindowTracingDataSource.java b/services/core/java/com/android/server/wm/WindowTracingDataSource.java index 3d2c0d3f79b9..6984f0dbab72 100644 --- a/services/core/java/com/android/server/wm/WindowTracingDataSource.java +++ b/services/core/java/com/android/server/wm/WindowTracingDataSource.java @@ -50,12 +50,14 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS } public static class Config { - public final @WindowTraceLogLevel int mLogLevel; - public final boolean mLogOnFrame; + public final @WindowTracingLogLevel int mLogLevel; + public final @WindowTracingLogFrequency int mLogFrequency; - private Config(@WindowTraceLogLevel int logLevel, boolean logOnFrame) { + private Config( + @WindowTracingLogLevel int logLevel, + @WindowTracingLogFrequency int logFrequency) { mLogLevel = logLevel; - mLogOnFrame = logOnFrame; + mLogFrequency = logFrequency; } } @@ -68,7 +70,8 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS } } - private static final Config CONFIG_DEFAULT = new Config(WindowTraceLogLevel.TRIM, true); + private static final Config CONFIG_DEFAULT = + new Config(WindowTracingLogLevel.TRIM, WindowTracingLogFrequency.FRAME); private static final int CONFIG_VALUE_UNSPECIFIED = 0; private static final String TAG = "WindowTracingDataSource"; @@ -160,45 +163,48 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS throw new RuntimeException("Failed to parse WindowManagerConfig", e); } - @WindowTraceLogLevel int logLevel; + @WindowTracingLogLevel int logLevel; switch(parsedLogLevel) { case CONFIG_VALUE_UNSPECIFIED: Log.w(TAG, "Unspecified log level. Defaulting to TRIM"); - logLevel = WindowTraceLogLevel.TRIM; + logLevel = WindowTracingLogLevel.TRIM; break; case WindowManagerConfig.LOG_LEVEL_VERBOSE: - logLevel = WindowTraceLogLevel.ALL; + logLevel = WindowTracingLogLevel.ALL; break; case WindowManagerConfig.LOG_LEVEL_DEBUG: - logLevel = WindowTraceLogLevel.TRIM; + logLevel = WindowTracingLogLevel.TRIM; break; case WindowManagerConfig.LOG_LEVEL_CRITICAL: - logLevel = WindowTraceLogLevel.CRITICAL; + logLevel = WindowTracingLogLevel.CRITICAL; break; default: Log.w(TAG, "Unrecognized log level. Defaulting to TRIM"); - logLevel = WindowTraceLogLevel.TRIM; + logLevel = WindowTracingLogLevel.TRIM; break; } - boolean logOnFrame; + @WindowTracingLogFrequency int logFrequency; switch(parsedLogFrequency) { case CONFIG_VALUE_UNSPECIFIED: - Log.w(TAG, "Unspecified log frequency. Defaulting to 'log on frame'"); - logOnFrame = true; + Log.w(TAG, "Unspecified log frequency. Defaulting to 'frame'"); + logFrequency = WindowTracingLogFrequency.FRAME; break; case WindowManagerConfig.LOG_FREQUENCY_FRAME: - logOnFrame = true; + logFrequency = WindowTracingLogFrequency.FRAME; break; case WindowManagerConfig.LOG_FREQUENCY_TRANSACTION: - logOnFrame = false; + logFrequency = WindowTracingLogFrequency.TRANSACTION; + break; + case WindowManagerConfig.LOG_FREQUENCY_SINGLE_DUMP: + logFrequency = WindowTracingLogFrequency.SINGLE_DUMP; break; default: - Log.w(TAG, "Unrecognized log frequency. Defaulting to 'log on frame'"); - logOnFrame = true; + Log.w(TAG, "Unrecognized log frequency. Defaulting to 'frame'"); + logFrequency = WindowTracingLogFrequency.FRAME; break; } - return new Config(logLevel, logOnFrame); + return new Config(logLevel, logFrequency); } } diff --git a/services/core/java/com/android/server/wm/WindowTracingLegacy.java b/services/core/java/com/android/server/wm/WindowTracingLegacy.java index 7a36707fd95a..34fd088cc2e1 100644 --- a/services/core/java/com/android/server/wm/WindowTracingLegacy.java +++ b/services/core/java/com/android/server/wm/WindowTracingLegacy.java @@ -30,6 +30,7 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.Choreographer; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.TraceBuffer; import java.io.File; @@ -58,7 +59,7 @@ class WindowTracingLegacy extends WindowTracing { private boolean mEnabled; private volatile boolean mEnabledLockFree; - protected @WindowTraceLogLevel int mLogLevel = WindowTraceLogLevel.TRIM; + protected @WindowTracingLogLevel int mLogLevel = WindowTracingLogLevel.TRIM; protected boolean mLogOnFrame = false; WindowTracingLegacy(WindowManagerService service, Choreographer choreographer) { @@ -66,6 +67,7 @@ class WindowTracingLegacy extends WindowTracing { service.mGlobalLock, BUFFER_CAPACITY_TRIM); } + @VisibleForTesting WindowTracingLegacy(File traceFile, WindowManagerService service, Choreographer choreographer, WindowManagerGlobalLock globalLock, int bufferSize) { super(service, choreographer, globalLock); @@ -74,20 +76,20 @@ class WindowTracingLegacy extends WindowTracing { } @Override - void setLogLevel(@WindowTraceLogLevel int logLevel, PrintWriter pw) { + void setLogLevel(@WindowTracingLogLevel int logLevel, PrintWriter pw) { logAndPrintln(pw, "Setting window tracing log level to " + logLevel); mLogLevel = logLevel; switch (logLevel) { - case WindowTraceLogLevel.ALL: { + case WindowTracingLogLevel.ALL: { setBufferCapacity(BUFFER_CAPACITY_ALL, pw); break; } - case WindowTraceLogLevel.TRIM: { + case WindowTracingLogLevel.TRIM: { setBufferCapacity(BUFFER_CAPACITY_TRIM, pw); break; } - case WindowTraceLogLevel.CRITICAL: { + case WindowTracingLogLevel.CRITICAL: { setBufferCapacity(BUFFER_CAPACITY_CRITICAL, pw); break; } @@ -141,19 +143,19 @@ class WindowTracingLegacy extends WindowTracing { String logLevelStr = shell.getNextArgRequired().toLowerCase(); switch (logLevelStr) { case "all": { - setLogLevel(WindowTraceLogLevel.ALL, pw); + setLogLevel(WindowTracingLogLevel.ALL, pw); break; } case "trim": { - setLogLevel(WindowTraceLogLevel.TRIM, pw); + setLogLevel(WindowTracingLogLevel.TRIM, pw); break; } case "critical": { - setLogLevel(WindowTraceLogLevel.CRITICAL, pw); + setLogLevel(WindowTracingLogLevel.CRITICAL, pw); break; } default: { - setLogLevel(WindowTraceLogLevel.TRIM, pw); + setLogLevel(WindowTracingLogLevel.TRIM, pw); break; } } diff --git a/services/core/java/com/android/server/wm/WindowTracingLogFrequency.java b/services/core/java/com/android/server/wm/WindowTracingLogFrequency.java new file mode 100644 index 000000000000..8e2c308837fb --- /dev/null +++ b/services/core/java/com/android/server/wm/WindowTracingLogFrequency.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@IntDef({ + WindowTracingLogFrequency.FRAME, + WindowTracingLogFrequency.TRANSACTION, + WindowTracingLogFrequency.SINGLE_DUMP, +}) +@Retention(RetentionPolicy.SOURCE) +@interface WindowTracingLogFrequency { + /** + * Trace state snapshots when a frame is committed. + */ + int FRAME = 0; + /** + * Trace state snapshots when a transaction is committed. + */ + int TRANSACTION = 1; + /** + * Trace single state snapshots when the Perfetto data source is started. + */ + int SINGLE_DUMP = 2; +} diff --git a/services/core/java/com/android/server/wm/WindowTraceLogLevel.java b/services/core/java/com/android/server/wm/WindowTracingLogLevel.java index 2165c66a10e8..4f901c6f5727 100644 --- a/services/core/java/com/android/server/wm/WindowTraceLogLevel.java +++ b/services/core/java/com/android/server/wm/WindowTracingLogLevel.java @@ -22,12 +22,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @IntDef({ - WindowTraceLogLevel.ALL, - WindowTraceLogLevel.TRIM, - WindowTraceLogLevel.CRITICAL, + WindowTracingLogLevel.ALL, + WindowTracingLogLevel.TRIM, + WindowTracingLogLevel.CRITICAL, }) @Retention(RetentionPolicy.SOURCE) -@interface WindowTraceLogLevel{ +@interface WindowTracingLogLevel { /** * Logs all elements with maximum amount of information. * diff --git a/services/core/java/com/android/server/wm/WindowTracingPerfetto.java b/services/core/java/com/android/server/wm/WindowTracingPerfetto.java index 653b6dac1537..cf948ca76f99 100644 --- a/services/core/java/com/android/server/wm/WindowTracingPerfetto.java +++ b/services/core/java/com/android/server/wm/WindowTracingPerfetto.java @@ -25,6 +25,8 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.Choreographer; +import com.android.internal.annotations.VisibleForTesting; + import java.io.PrintWriter; import java.util.concurrent.atomic.AtomicInteger; @@ -37,11 +39,17 @@ class WindowTracingPerfetto extends WindowTracing { this::onStart, this::onStop); WindowTracingPerfetto(WindowManagerService service, Choreographer choreographer) { - super(service, choreographer, service.mGlobalLock); + this(service, choreographer, service.mGlobalLock); + } + + @VisibleForTesting + WindowTracingPerfetto(WindowManagerService service, Choreographer choreographer, + WindowManagerGlobalLock globalLock) { + super(service, choreographer, globalLock); } @Override - void setLogLevel(@WindowTraceLogLevel int logLevel, PrintWriter pw) { + void setLogLevel(@WindowTracingLogLevel int logLevel, PrintWriter pw) { logAndPrintln(pw, "Log level must be configured through perfetto"); } @@ -110,7 +118,15 @@ class WindowTracingPerfetto extends WindowTracing { if (!isDataSourceStarting) { return; } - } else if (isOnFrameLogEvent != dataSourceConfig.mLogOnFrame) { + } else if (isOnFrameLogEvent) { + boolean isDataSourceLoggingOnFrame = + dataSourceConfig.mLogFrequency == WindowTracingLogFrequency.FRAME; + if (!isDataSourceLoggingOnFrame) { + return; + } + } else if (dataSourceConfig.mLogFrequency + == WindowTracingLogFrequency.SINGLE_DUMP) { + // If it is a dump, write only the start log event and skip the following ones return; } @@ -141,21 +157,21 @@ class WindowTracingPerfetto extends WindowTracing { } private void onStart(WindowTracingDataSource.Config config) { - if (config.mLogOnFrame) { + if (config.mLogFrequency == WindowTracingLogFrequency.FRAME) { mCountSessionsOnFrame.incrementAndGet(); - } else { + } else if (config.mLogFrequency == WindowTracingLogFrequency.TRANSACTION) { mCountSessionsOnTransaction.incrementAndGet(); } Log.i(TAG, "Started with logLevel: " + config.mLogLevel - + " logOnFrame: " + config.mLogOnFrame); + + " logFrequency: " + config.mLogFrequency); log(WHERE_START_TRACING); } private void onStop(WindowTracingDataSource.Config config) { - if (config.mLogOnFrame) { + if (config.mLogFrequency == WindowTracingLogFrequency.FRAME) { mCountSessionsOnFrame.decrementAndGet(); - } else { + } else if (config.mLogFrequency == WindowTracingLogFrequency.TRANSACTION) { mCountSessionsOnTransaction.decrementAndGet(); } Log.i(TAG, "Stopped"); diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 4d6a90c81b27..07d39d957d70 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -291,6 +291,7 @@ public: void setTouchpadNaturalScrollingEnabled(bool enabled); void setTouchpadTapToClickEnabled(bool enabled); void setTouchpadTapDraggingEnabled(bool enabled); + void setShouldNotifyTouchpadHardwareState(bool enabled); void setTouchpadRightClickZoneEnabled(bool enabled); void setInputDeviceEnabled(uint32_t deviceId, bool enabled); void setShowTouches(bool enabled); @@ -440,6 +441,9 @@ private: // True to enable tap dragging on touchpads. bool touchpadTapDraggingEnabled{false}; + // True if hardware state update notifications should be sent to the policy. + bool shouldNotifyTouchpadHardwareState{false}; + // True to enable a zone on the right-hand side of touchpads where clicks will be turned // into context (a.k.a. "right") clicks. bool touchpadRightClickZoneEnabled{false}; @@ -698,6 +702,7 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon outConfig->touchpadNaturalScrollingEnabled = mLocked.touchpadNaturalScrollingEnabled; outConfig->touchpadTapToClickEnabled = mLocked.touchpadTapToClickEnabled; outConfig->touchpadTapDraggingEnabled = mLocked.touchpadTapDraggingEnabled; + outConfig->shouldNotifyTouchpadHardwareState = mLocked.shouldNotifyTouchpadHardwareState; outConfig->touchpadRightClickZoneEnabled = mLocked.touchpadRightClickZoneEnabled; outConfig->disabledDevices = mLocked.disabledInputDevices; @@ -1260,6 +1265,22 @@ void NativeInputManager::setTouchpadTapDraggingEnabled(bool enabled) { InputReaderConfiguration::Change::TOUCHPAD_SETTINGS); } +void NativeInputManager::setShouldNotifyTouchpadHardwareState(bool enabled) { + { // acquire lock + std::scoped_lock _l(mLock); + + if (mLocked.shouldNotifyTouchpadHardwareState == enabled) { + return; + } + + ALOGI("Should touchpad hardware state be notified: %s.", toString(enabled)); + mLocked.shouldNotifyTouchpadHardwareState = enabled; + } // release lock + + mInputManager->getReader().requestRefreshConfiguration( + InputReaderConfiguration::Change::TOUCHPAD_SETTINGS); +} + void NativeInputManager::setTouchpadRightClickZoneEnabled(bool enabled) { { // acquire lock std::scoped_lock _l(mLock); @@ -2144,6 +2165,13 @@ static void nativeSetTouchpadTapDraggingEnabled(JNIEnv* env, jobject nativeImplO im->setTouchpadTapDraggingEnabled(enabled); } +static void nativeSetShouldNotifyTouchpadHardwareState(JNIEnv* env, jobject nativeImplObj, + jboolean enabled) { + NativeInputManager* im = getNativeInputManager(env, nativeImplObj); + + im->setShouldNotifyTouchpadHardwareState(enabled); +} + static void nativeSetTouchpadRightClickZoneEnabled(JNIEnv* env, jobject nativeImplObj, jboolean enabled) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); @@ -2762,6 +2790,8 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*)nativeSetTouchpadNaturalScrollingEnabled}, {"setTouchpadTapToClickEnabled", "(Z)V", (void*)nativeSetTouchpadTapToClickEnabled}, {"setTouchpadTapDraggingEnabled", "(Z)V", (void*)nativeSetTouchpadTapDraggingEnabled}, + {"setShouldNotifyTouchpadHardwareState", "(Z)V", + (void*)nativeSetShouldNotifyTouchpadHardwareState}, {"setTouchpadRightClickZoneEnabled", "(Z)V", (void*)nativeSetTouchpadRightClickZoneEnabled}, {"setShowTouches", "(Z)V", (void*)nativeSetShowTouches}, {"setInteractive", "(Z)V", (void*)nativeSetInteractive}, diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index f12930a49ecb..5c5ac28b2169 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -198,7 +198,8 @@ static Aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primit } static Aidl::VendorEffect vendorEffectFromJavaParcel(JNIEnv* env, jobject vendorData, - jlong strength, jfloat scale) { + jlong strength, jfloat scale, + jfloat adaptiveScale) { PersistableBundle bundle; if (AParcel* parcel = AParcel_fromJavaParcel(env, vendorData); parcel != nullptr) { if (binder_status_t status = bundle.readFromParcel(parcel); status == STATUS_OK) { @@ -217,6 +218,7 @@ static Aidl::VendorEffect vendorEffectFromJavaParcel(JNIEnv* env, jobject vendor effect.vendorData = bundle; effect.strength = static_cast<Aidl::EffectStrength>(strength); effect.scale = static_cast<float>(scale); + effect.vendorScale = static_cast<float>(adaptiveScale); return effect; } @@ -319,13 +321,14 @@ static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, j static jlong vibratorPerformVendorEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jobject vendorData, jlong strength, jfloat scale, - jlong vibrationId) { + jfloat adaptiveScale, jlong vibrationId) { VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); if (wrapper == nullptr) { ALOGE("vibratorPerformVendorEffect failed because native wrapper was not initialized"); return -1; } - Aidl::VendorEffect effect = vendorEffectFromJavaParcel(env, vendorData, strength, scale); + Aidl::VendorEffect effect = + vendorEffectFromJavaParcel(env, vendorData, strength, scale, adaptiveScale); auto callback = wrapper->createCallback(vibrationId); auto performVendorEffectFn = [&effect, &callback](vibrator::HalWrapper* hal) { return hal->performVendorEffect(effect, callback); @@ -511,7 +514,7 @@ static const JNINativeMethod method_table[] = { {"off", "(J)V", (void*)vibratorOff}, {"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude}, {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect}, - {"performVendorEffect", "(JLandroid/os/Parcel;JFJ)J", (void*)vibratorPerformVendorEffect}, + {"performVendorEffect", "(JLandroid/os/Parcel;JFFJ)J", (void*)vibratorPerformVendorEffect}, {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;J)J", (void*)vibratorPerformComposedEffect}, {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJ)J", diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 9ed645b6ca9b..d5013517cd88 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12215,34 +12215,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * permittedList or are a system app. */ private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages, - List<String> permittedList, int userIdToCheck) { + List<String> permittedList, int userId) { long id = mInjector.binderClearCallingIdentity(); try { - // If we have an enabled packages list for a managed profile the packages - // we should check are installed for the parent user. - UserInfo user = getUserInfo(userIdToCheck); - if (user.isManagedProfile()) { - userIdToCheck = user.profileGroupId; - } - for (String enabledPackage : enabledPackages) { - boolean systemService = false; + if (permittedList.contains(enabledPackage)) { + continue; + } try { ApplicationInfo applicationInfo = mIPackageManager.getApplicationInfo( - enabledPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES, - userIdToCheck); + enabledPackage, PackageManager.MATCH_ANY_USER, userId); if (applicationInfo == null) { + Slogf.wtf(LOG_TAG, "Can't find ApplicationInfo for %s", enabledPackage); return false; } - systemService = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + if (!applicationInfo.isSystemApp()) { + Slogf.w(LOG_TAG, + "Enabled package neither permitted nor system: %s", enabledPackage); + return false; + } } catch (RemoteException e) { Slogf.i(LOG_TAG, "Can't talk to package managed", e); } - if (!systemService && !permittedList.contains(enabledPackage)) { - return false; - } } } finally { mInjector.binderRestoreCallingIdentity(id); diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp index 6393e11b7432..1db9e8d545e4 100644 --- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp +++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp @@ -1,7 +1,7 @@ aconfig_declarations { name: "device_state_flags", package: "com.android.server.policy.feature.flags", - container: "system", + container: "system_ext", srcs: [ "device_state_flags.aconfig", ], diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig index 21e33dd1b99a..f827b5508015 100644 --- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig +++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig @@ -1,5 +1,5 @@ package: "com.android.server.policy.feature.flags" -container: "system" +container: "system_ext" flag { name: "enable_dual_display_blocking" diff --git a/services/proguard.flags b/services/proguard.flags index bf30781b434e..cdd41abf6c7c 100644 --- a/services/proguard.flags +++ b/services/proguard.flags @@ -52,9 +52,6 @@ -keep public class com.android.server.utils.Slogf { *; } # Referenced in wear-service -# HIDL interfaces --keep public class android.hidl.base.** { *; } --keep public class android.hidl.manager.** { *; } -keep public class com.android.server.wm.WindowManagerInternal { *; } # JNI keep rules @@ -107,8 +104,23 @@ -keep,allowoptimization,allowaccessmodification class com.android.server.SystemService { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.SystemService$TargetUser { *; } -keep,allowoptimization,allowaccessmodification class com.android.server.usage.StorageStatsManagerLocal { *; } --keep,allowoptimization,allowaccessmodification class com.android.internal.util.** { *; } --keep,allowoptimization,allowaccessmodification class android.os.** { *; } + +# Prevent optimizations of any statically linked code that may shadow code in +# the bootclasspath. See also StrictJavaPackagesTest for details on exceptions. +# TODO(b/222468116): Resolve such collisions in the build system. +-keep public class android.gsi.** { *; } +-keep public class android.hidl.base.** { *; } +-keep public class android.hidl.manager.** { *; } +-keep public class android.os.** { *; } +-keep public class com.android.internal.util.** { *; } +-keep public class com.android.modules.utils.build.** { *; } +# Also suppress related duplicate type warnings for the above kept classes. +-dontwarn android.gsi.** +-dontwarn android.hidl.base.** +-dontwarn android.hidl.manager.** +-dontwarn android.os.** +-dontwarn com.android.internal.util.** +-dontwarn com.android.modules.utils.build.** # CoverageService guards optional jacoco class references with a runtime guard, so we can safely # suppress build-time warnings. diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 2a458c42b841..312df4391e2d 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -194,7 +194,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0 /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); } @Test @@ -300,7 +300,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0.5f /* brightness= */, true /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); // There should be a user data point added to the mapper. verify(mBrightnessMappingStrategy).addUserDataPoint(/* lux= */ 1000f, @@ -324,7 +324,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0.5f /* brightness= */, true /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); //Recalculating the spline with RBC enabled, verifying that the short term model is reset, //and the interaction is learnt in short term model @@ -358,7 +358,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0.5f, /* userChangedBrightness= */ true, /* adjustment= */ 0, /* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); when(mBrightnessMappingStrategy.getShortTermModelTimeout()).thenReturn(2000L); @@ -398,7 +398,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0.51f /* brightness= */, true /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); when(mBrightnessMappingStrategy.shouldResetShortTermModel( anyFloat(), anyFloat())).thenReturn(true); @@ -438,7 +438,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0.5f, /* userChangedBrightness= */ true, /* adjustment= */ 0, /* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); when(mBrightnessMappingStrategy.getShortTermModelTimeout()).thenReturn(2000L); when(mBrightnessMappingStrategy.getUserBrightness()).thenReturn(0.5f); @@ -484,7 +484,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0.5f, /* userChangedBrightness= */ true, /* adjustment= */ 0, /* userChanged= */ false, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); when(mBrightnessMappingStrategy.getShortTermModelTimeout()).thenReturn(2000L); @@ -571,7 +571,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0.5f /* brightness= */, true /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); // There should be a user data point added to the mapper. verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f, @@ -598,7 +598,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, 0.5f /* brightness= */, true /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); // Ensure we use the correct mapping strategy verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f, @@ -759,7 +759,8 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ true); + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ true); assertEquals(throttledBrightness, mController.getAutomaticScreenBrightness(), 0.0f); // The raw brightness value should not have throttling applied assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getRawAutomaticScreenBrightness(), 0.0f); @@ -770,7 +771,8 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ true); + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ true); assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getAutomaticScreenBrightness(), 0.0f); assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getRawAutomaticScreenBrightness(), 0.0f); } @@ -907,13 +909,15 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ false); + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false); verify(mBrightnessMappingStrategy, never()).clearUserDataPoints(); mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ true); + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ true); verify(mBrightnessMappingStrategy).clearUserDataPoints(); } @@ -1100,7 +1104,7 @@ public class AutomaticBrightnessControllerTest { mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_DOZE, - /* shouldResetShortTermModel= */ true); + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); @@ -1112,7 +1116,10 @@ public class AutomaticBrightnessControllerTest { } @Test - public void testAutoBrightnessInDoze_ShouldNotScaleIfUsingDozeCurve() throws Exception { + public void testAutoBrightnessInDoze_useNormalBrightnessForDozeFalse_scaleScreenOn() + throws Exception { + when(mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1125,18 +1132,51 @@ public class AutomaticBrightnessControllerTest { float normalizedBrightness = 0.3f; when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); - when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - // Switch mode to DOZE - mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); + // Set policy to DOZE + mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, + /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, + /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_ON, + /* useNormalBrightnessForDoze= */ false, /* shouldResetShortTermModel= */ true); + + // Send a new sensor value + listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); + + // The brightness should be scaled by the doze factor + assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR, + mController.getAutomaticScreenBrightness( + /* brightnessEvent= */ null), EPSILON); + } + + @Test + public void testAutoBrightnessInDoze_useNormalBrightnessForDozeTrue_notScaleScreenOn() + throws Exception { + when(mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + + ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), + eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class)); + SensorEventListener listener = listenerCaptor.getValue(); + + // Set up system to return 0.3f as a brightness value + float lux = 100.0f; + // Brightness as float (from 0.0f to 1.0f) + float normalizedBrightness = 0.3f; + when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); + when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); + when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + /* category= */ anyInt())).thenReturn(normalizedBrightness); + when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, - /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_DOZE, - /* shouldResetShortTermModel= */ true); + /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_ON, + /* useNormalBrightnessForDoze= */ true, /* shouldResetShortTermModel= */ true); // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); @@ -1147,7 +1187,7 @@ public class AutomaticBrightnessControllerTest { } @Test - public void testAutoBrightnessInDoze_ShouldNotScaleIfScreenOn() throws Exception { + public void testAutoBrightnessInDoze_ShouldNotScaleIfUsingDozeCurve() throws Exception { ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), @@ -1160,15 +1200,18 @@ public class AutomaticBrightnessControllerTest { float normalizedBrightness = 0.3f; when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux); when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); - when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), + when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + // Switch mode to DOZE + mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); + // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0, - /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_ON, - /* shouldResetShortTermModel= */ true); + /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE, Display.STATE_DOZE, + /* useNormalBrightnessForDoze= */ true, /* shouldResetShortTermModel= */ true); // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index 2b03dc4f78ad..bbf2ecbb9380 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -69,7 +69,6 @@ import android.app.PropertyInvalidatedCache; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; -import android.companion.virtual.flags.Flags; import android.compat.testing.PlatformCompatChangeRule; import android.content.BroadcastReceiver; import android.content.Context; @@ -374,7 +373,6 @@ public class DisplayManagerServiceTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false); - mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); mLocalServiceKeeperRule.overrideLocalService( InputManagerInternal.class, mMockInputManagerInternal); @@ -1298,44 +1296,11 @@ public class DisplayManagerServiceTest { } /** - * Tests that it's not allowed to create an auto-mirror virtual display when display mirroring - * is not supported in a virtual device. - */ - @Test - public void createAutoMirrorDisplay_virtualDeviceDoesntSupportMirroring_throwsException() - throws Exception { - mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); - DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); - DisplayManagerInternal localService = displayManager.new LocalService(); - registerDefaultDisplays(displayManager); - when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); - when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn( - PackageManager.PERMISSION_DENIED); - IVirtualDevice virtualDevice = mock(IVirtualDevice.class); - when(virtualDevice.getDeviceId()).thenReturn(1); - when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); - - final VirtualDisplayConfig.Builder builder = - new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320) - .setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) - .setUniqueId("uniqueId --- mirror display"); - assertThrows(SecurityException.class, () -> { - localService.createVirtualDisplay( - builder.build(), - mMockAppToken /* callback */, - virtualDevice /* virtualDeviceToken */, - mock(DisplayWindowPolicyController.class), - PACKAGE_NAME); - }); - } - - /** * Tests that the virtual display is added to the default display group when created with * VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR using a virtual device. */ @Test public void createAutoMirrorVirtualDisplay_addsDisplayToDefaultDisplayGroup() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); @@ -1368,7 +1333,6 @@ public class DisplayManagerServiceTest { */ @Test public void createAutoMirrorVirtualDisplay_mirrorsDefaultDisplay() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); @@ -1400,7 +1364,6 @@ public class DisplayManagerServiceTest { */ @Test public void createOwnContentOnlyVirtualDisplay_doesNotMirrorAnyDisplay() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); @@ -1436,7 +1399,6 @@ public class DisplayManagerServiceTest { */ @Test public void createAutoMirrorVirtualDisplay_flagAlwaysUnlockedNotSet() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); @@ -1472,7 +1434,6 @@ public class DisplayManagerServiceTest { */ @Test public void createAutoMirrorVirtualDisplay_flagPresentationNotSet() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index b5278a5818a8..5840cb937e67 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -1014,7 +1014,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ false + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController) .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED); @@ -1040,7 +1041,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, - Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + Display.STATE_DOZE, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController) .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED); @@ -1070,7 +1072,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, - Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + Display.STATE_DOZE, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController) .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED); @@ -1093,7 +1096,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ false + Display.STATE_ON, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController) .setAutoBrightnessEnabled(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED); @@ -1116,7 +1120,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_OFF, - Display.STATE_OFF, /* shouldResetShortTermModel= */ false + Display.STATE_OFF, /* useNormalBrightnessForDoze */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController).setAutoBrightnessEnabled( AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE); @@ -1142,7 +1147,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, - Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + Display.STATE_DOZE, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController).setAutoBrightnessEnabled( AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE); @@ -1172,7 +1178,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_DOZE, - Display.STATE_DOZE, /* shouldResetShortTermModel= */ false + Display.STATE_DOZE, /* useNormalBrightnessForDoze= */ false, + /* shouldResetShortTermModel= */ false ); verify(mHolder.hbmController).setAutoBrightnessEnabled( AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE); @@ -1196,7 +1203,8 @@ public final class DisplayPowerControllerTest { /* configuration= */ null, PowerManager.BRIGHTNESS_INVALID_FLOAT, /* userChangedBrightness= */ false, /* adjustment= */ 0, /* userChangedAutoBrightnessAdjustment= */ false, DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, /* shouldResetShortTermModel= */ false + Display.STATE_ON, /* useNormalBrightnessForDoze */ false, + /* shouldResetShortTermModel= */ false ); // HBM should be allowed for the follower display @@ -1613,16 +1621,21 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState reset(mHolder.wakelockController); + when(mHolder.wakelockController + .acquireWakelock(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)) + .thenReturn(true); mHolder.dpc.overrideDozeScreenState( supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); - advanceTime(1); // Run updatePowerState // Should get a wakelock to notify powermanager - verify(mHolder.wakelockController, atLeastOnce()).acquireWakelock( - eq(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS)); + verify(mHolder.wakelockController).acquireWakelock( + eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); + advanceTime(1); // Run updatePowerState verify(mHolder.displayPowerState) .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY); + verify(mHolder.wakelockController).releaseWakelock( + eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE)); } @Test @@ -1955,6 +1968,7 @@ public final class DisplayPowerControllerTest { /* userChangedAutoBrightnessAdjustment= */ anyBoolean(), /* displayPolicy= */ anyInt(), /* displayState= */ anyInt(), + /* useNormalBrightnessForDoze= */ anyBoolean(), /* shouldResetShortTermModel= */ anyBoolean()); verify(mBrightnessTrackerMock, never()).notifyBrightnessChanged( /* brightness= */ anyFloat(), @@ -2040,6 +2054,75 @@ public final class DisplayPowerControllerTest { } @Test + public void testManualBrightness_stateOnPolicyDozeUseNormalBrightnessForDozeFalse_brightnessDoze() { + when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + when(mDisplayManagerFlagsMock.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + float brightness = 0.277f; + when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); + when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness); + when(mHolder.hbmController.getCurrentBrightnessMax()) + .thenReturn(PowerManager.BRIGHTNESS_MAX); + when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + dpr.dozeScreenState = Display.STATE_ON; + dpr.policy = DisplayPowerRequest.POLICY_DOZE; + dpr.useNormalBrightnessForDoze = false; + // Confirm using doze brightness for dozing device. + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState, initialize + + ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor = + ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + + verify(mHolder.animator).animateTo(eq(brightness * DOZE_SCALE_FACTOR), + /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), + /* ignoreAnimationLimits= */ anyBoolean()); + } + + @Test + public void testManualBrightness_stateOnPolicyDozeUseNormalBrightnessForDozeTrue_brightnessNormal() { + when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); + when(mDisplayManagerFlagsMock.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession); + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + float brightness = 0.277f; + when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f); + when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness); + when(mHolder.hbmController.getCurrentBrightnessMax()) + .thenReturn(PowerManager.BRIGHTNESS_MAX); + when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); + + DisplayPowerRequest dpr = new DisplayPowerRequest(); + dpr.dozeScreenState = Display.STATE_ON; + dpr.policy = DisplayPowerRequest.POLICY_DOZE; + dpr.useNormalBrightnessForDoze = true; + mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); + advanceTime(1); // Run updatePowerState, initialize + + ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor = + ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class); + verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture()); + BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue(); + listener.onBrightnessChanged(brightness); + advanceTime(1); // Send messages, run updatePowerState + + verify(mHolder.animator).animateTo(eq(brightness), + /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(), + /* ignoreAnimationLimits= */ anyBoolean()); + } + + @Test public void testDozeManualBrightness_AbcIsNull() { when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true); mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ true, diff --git a/services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java index c23d4b19cd3a..019b70ef1424 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/WakelockControllerTest.java @@ -64,6 +64,8 @@ public final class WakelockControllerTest { "[" + DISPLAY_ID + "]prox negative"); assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(), "[" + DISPLAY_ID + "]prox debounce"); + assertEquals(mWakelockController.getSuspendBlockerOverrideDozeScreenState(), + "[" + DISPLAY_ID + "]override doze screen state"); } @Test @@ -162,6 +164,28 @@ public final class WakelockControllerTest { } @Test + public void acquireOverrideDozeScreenStateSuspendBlocker() throws Exception { + // Acquire the suspend blocker + verifyWakelockAcquisitionAndReaquisition(WakelockController + .WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, + () -> mWakelockController.isOverrideDozeScreenStateAcquired()); + + // Verify acquire happened only once + verify(mDisplayPowerCallbacks, times(1)) + .acquireSuspendBlocker(mWakelockController + .getSuspendBlockerOverrideDozeScreenState()); + + // Release the suspend blocker + verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE, + () -> mWakelockController.isOverrideDozeScreenStateAcquired()); + + // Verify suspend blocker was released only once + verify(mDisplayPowerCallbacks, times(1)) + .releaseSuspendBlocker(mWakelockController + .getSuspendBlockerOverrideDozeScreenState()); + } + + @Test public void proximityPositiveRunnableWorksAsExpected() { // Acquire the suspend blocker twice assertTrue(mWakelockController.acquireWakelock( diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java index 639d06d21510..a44c517ed9cf 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java @@ -187,7 +187,7 @@ public final class DisplayBrightnessStrategySelectorTest { } @Test - public void selectStrategySelectsDozeStrategyWhenValid() { + public void selectStrategyWhenValid_useNormalBrightnessForDozeFalse_SelectsDozeStrategy() { DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock( DisplayManagerInternal.DisplayPowerRequest.class); displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; @@ -201,6 +201,22 @@ public final class DisplayBrightnessStrategySelectorTest { } @Test + public void selectStrategyWhenValid_useNormalBrightnessForDozeTrue_doNotSelectsDozeStrategy() { + when(mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock( + DisplayManagerInternal.DisplayPowerRequest.class); + displayPowerRequest.policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; + displayPowerRequest.dozeScreenBrightness = 0.2f; + displayPowerRequest.useNormalBrightnessForDoze = true; + when(mResources.getBoolean(R.bool.config_allowAutoBrightnessWhileDozing)).thenReturn( + DISALLOW_AUTO_BRIGHTNESS_WHILE_DOZING); + assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy( + new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE, + 0.1f, false, mDisplayOffloadSession)), + mDozeBrightnessModeStrategy); + } + + @Test public void selectStrategyDoesNotSelectDozeStrategyWhenInvalidBrightness() { DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock( DisplayManagerInternal.DisplayPowerRequest.class); @@ -353,7 +369,8 @@ public final class DisplayBrightnessStrategySelectorTest { mAutomaticBrightnessStrategy); verify(mAutomaticBrightnessStrategy).setAutoBrightnessState(Display.STATE_ON, true, BrightnessReason.REASON_UNKNOWN, - DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f, false); + DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, + /* useNormalBrightnessForDoze= */ false, 0.1f, false); } @Test diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java index 4e10b98c0041..e38654225c29 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java @@ -56,6 +56,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class AutomaticBrightnessStrategy2Test { private static final int DISPLAY_ID = 0; + + private static final boolean DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE = false; + @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); @@ -78,7 +81,8 @@ public class AutomaticBrightnessStrategy2Test { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Float.NaN); Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.5f); - mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy2(mContext, DISPLAY_ID); + mAutomaticBrightnessStrategy = + new AutomaticBrightnessStrategy2(mContext, DISPLAY_ID); mBrightnessConfiguration = new BrightnessConfiguration.Builder( new float[]{0f, 1f}, new float[]{0, PowerManager.BRIGHTNESS_ON}).build(); @@ -106,15 +110,18 @@ public class AutomaticBrightnessStrategy2Test { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -130,15 +137,18 @@ public class AutomaticBrightnessStrategy2Test { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -152,17 +162,20 @@ public class AutomaticBrightnessStrategy2Test { int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; float lastUserSetBrightness = 0.2f; boolean userSetBrightnessChanged = true; + boolean useNormalBrightnessForDoze = false; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + useNormalBrightnessForDoze, /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -178,15 +191,18 @@ public class AutomaticBrightnessStrategy2Test { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -200,19 +216,21 @@ public class AutomaticBrightnessStrategy2Test { int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; float lastUserSetBrightness = 0.2f; boolean userSetBrightnessChanged = true; + boolean useNormalBrightnessForDoze = false; Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.4f, - /* userChangedAutoBrightnessAdjustment= */ true, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + useNormalBrightnessForDoze, /* shouldResetShortTermModel */ true); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -226,19 +244,20 @@ public class AutomaticBrightnessStrategy2Test { int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; float lastUserSetBrightness = 0.2f; boolean userSetBrightnessChanged = true; + boolean useNormalBrightnessForDoze = false; Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.4f, - /* userChangedAutoBrightnessAdjustment= */ true, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + useNormalBrightnessForDoze, /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -257,14 +276,16 @@ public class AutomaticBrightnessStrategy2Test { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, pendingBrightnessAdjustment, /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* shouldResetShortTermModel */ true); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); @@ -280,19 +301,20 @@ public class AutomaticBrightnessStrategy2Test { boolean userSetBrightnessChanged = true; int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; float pendingBrightnessAdjustment = 0.1f; + boolean useNormalBrightnessForDoze = false; Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, pendingBrightnessAdjustment, /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, - /* shouldResetShortTermModel */ true); + useNormalBrightnessForDoze, /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -312,13 +334,15 @@ public class AutomaticBrightnessStrategy2Test { mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); setTemporaryAutoBrightnessAdjustment(temporaryAutoBrightnessAdjustments); mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, - lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration, - autoBrightnessState); + lastUserSetScreenBrightness, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + brightnessConfiguration, autoBrightnessState); verify(mAutomaticBrightnessController).configure(autoBrightnessState, brightnessConfiguration, lastUserSetScreenBrightness, userSetBrightnessChanged, temporaryAutoBrightnessAdjustments, /* userChangedAutoBrightnessAdjustment= */ false, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* shouldResetShortTermModel= */ true); assertTrue(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); assertFalse(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); @@ -328,8 +352,9 @@ public class AutomaticBrightnessStrategy2Test { mAutomaticBrightnessStrategy.setAutomaticBrightnessController(null); mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, - lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration, - autoBrightnessState); + lastUserSetScreenBrightness, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + brightnessConfiguration, autoBrightnessState); assertFalse(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); assertTrue(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive()); diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java index 93ff9e11d52f..50f814da6488 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java @@ -23,7 +23,9 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -62,6 +64,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class AutomaticBrightnessStrategyTest { private static final int DISPLAY_ID = 0; + + private static final boolean DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE = false; + @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); @@ -116,15 +121,18 @@ public class AutomaticBrightnessStrategyTest { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -140,15 +148,18 @@ public class AutomaticBrightnessStrategyTest { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -164,15 +175,18 @@ public class AutomaticBrightnessStrategyTest { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -188,15 +202,18 @@ public class AutomaticBrightnessStrategyTest { boolean userSetBrightnessChanged = true; mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.5f, /* userChangedAutoBrightnessAdjustment= */ false, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -214,15 +231,17 @@ public class AutomaticBrightnessStrategyTest { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.4f, - /* userChangedAutoBrightnessAdjustment= */ true, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -240,15 +259,17 @@ public class AutomaticBrightnessStrategyTest { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.4f); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, /* adjustment */ 0.4f, - /* userChangedAutoBrightnessAdjustment= */ true, policy, - targetDisplayState, /* shouldResetShortTermModel */ true); + /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); } @@ -267,14 +288,16 @@ public class AutomaticBrightnessStrategyTest { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, mBrightnessConfiguration, lastUserSetBrightness, userSetBrightnessChanged, pendingBrightnessAdjustment, /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* shouldResetShortTermModel */ true); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); @@ -294,7 +317,8 @@ public class AutomaticBrightnessStrategyTest { Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, + allowAutoBrightnessWhileDozing, brightnessReason, policy, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController) .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE, @@ -302,6 +326,7 @@ public class AutomaticBrightnessStrategyTest { lastUserSetBrightness, userSetBrightnessChanged, pendingBrightnessAdjustment, /* userChangedAutoBrightnessAdjustment= */ true, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* shouldResetShortTermModel */ true); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessDisabledDueToDisplayOff()); @@ -318,6 +343,7 @@ public class AutomaticBrightnessStrategyTest { boolean userSetBrightnessChanged = true; int policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT; float pendingBrightnessAdjustment = 0.1f; + boolean useNormalBrightnessForDoze = false; Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingBrightnessAdjustment); mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments(); @@ -325,8 +351,8 @@ public class AutomaticBrightnessStrategyTest { // Validate no interaction when automaticBrightnessController is in idle mode when(mAutomaticBrightnessController.isInIdleMode()).thenReturn(true); mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController, never()) .switchMode(anyInt(), /* sendUpdate= */ anyBoolean()); @@ -334,20 +360,57 @@ public class AutomaticBrightnessStrategyTest { // state is ON when(mAutomaticBrightnessController.isInIdleMode()).thenReturn(false); mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); verify(mAutomaticBrightnessController).switchMode( AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT, /* sendUpdate= */ false); - // Validate interaction when automaticBrightnessController is in non-idle mode, and display - // state is DOZE + reset(mAutomaticBrightnessController); + when(mAutomaticBrightnessController.isInIdleMode()).thenReturn(false); + when(mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()).thenReturn(true); + policy = DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE; + + // Validate interaction when automaticBrightnessController is in non-idle mode, display + // state is DOZE, policy is DOZE and useNormalBrightnessForDoze is false. mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_DOZE, - allowAutoBrightnessWhileDozing, brightnessReason, policy, lastUserSetBrightness, - userSetBrightnessChanged); + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); + // 1st AUTO_BRIGHTNESS_MODE_DOZE verify(mAutomaticBrightnessController).switchMode( AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); + + // Validate interaction when automaticBrightnessController is in non-idle mode, display + // state is ON, policy is DOZE and useNormalBrightnessForDoze is false. + mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); + // 2nd AUTO_BRIGHTNESS_MODE_DOZE + verify(mAutomaticBrightnessController, times(2)).switchMode( + AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE, + /* sendUpdate= */ false); + + useNormalBrightnessForDoze = true; + // Validate interaction when automaticBrightnessController is in non-idle mode, display + // state is DOZE, policy is DOZE and useNormalBrightnessForDoze is true. + mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_DOZE, + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); + // 1st AUTO_BRIGHTNESS_MODE_DEFAULT + verify(mAutomaticBrightnessController).switchMode( + AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT, + /* sendUpdate= */ false); + + // Validate interaction when automaticBrightnessController is in non-idle mode, display + // state is ON, policy is DOZE and useNormalBrightnessForDoze is true. + mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, + allowAutoBrightnessWhileDozing, brightnessReason, policy, + useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged); + // 2nd AUTO_BRIGHTNESS_MODE_DEFAULT + verify(mAutomaticBrightnessController, times(2)).switchMode( + AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT, + /* sendUpdate= */ false); } @Test @@ -365,13 +428,15 @@ public class AutomaticBrightnessStrategyTest { mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); setTemporaryAutoBrightnessAdjustment(temporaryAutoBrightnessAdjustments); mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, - lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration, - autoBrightnessState); + lastUserSetScreenBrightness, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + brightnessConfiguration, autoBrightnessState); verify(mAutomaticBrightnessController).configure(autoBrightnessState, brightnessConfiguration, lastUserSetScreenBrightness, userSetBrightnessChanged, temporaryAutoBrightnessAdjustments, /* userChangedAutoBrightnessAdjustment= */ false, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* shouldResetShortTermModel= */ true); assertTrue(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); assertFalse(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); @@ -381,8 +446,9 @@ public class AutomaticBrightnessStrategyTest { mAutomaticBrightnessStrategy.setAutomaticBrightnessController(null); mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true); mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged, - lastUserSetScreenBrightness, policy, targetDisplayState, brightnessConfiguration, - autoBrightnessState); + lastUserSetScreenBrightness, policy, targetDisplayState, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + brightnessConfiguration, autoBrightnessState); assertFalse(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied()); assertTrue(mAutomaticBrightnessStrategy.shouldResetShortTermModel()); assertFalse(mAutomaticBrightnessStrategy.isShortTermModelActive()); @@ -504,8 +570,9 @@ public class AutomaticBrightnessStrategyTest { public void isAutoBrightnessValid_returnsFalseWhenBrightnessIsInvalid() { mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, true, BrightnessReason.REASON_UNKNOWN, - DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f, - false); + DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* lastUserSetScreenBrightness= */ 0.1f, + /* userSetBrightnessChanged= */ false); when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null)) .thenReturn(Float.NaN); assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessValid()); @@ -520,8 +587,9 @@ public class AutomaticBrightnessStrategyTest { .thenReturn(0.1f); mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON, true, BrightnessReason.REASON_UNKNOWN, - DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, 0.1f, - false); + DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, + DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* lastUserSetScreenBrightness= */ 0.1f, + /* userSetBrightnessChanged= */ false); when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null)) .thenReturn(0.2f); assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessValid()); @@ -594,7 +662,8 @@ public class AutomaticBrightnessStrategyTest { mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment(temporaryBrightness); mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(true, brightness, DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT, - Display.STATE_ON, mock(BrightnessConfiguration.class), + Display.STATE_ON, DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, + mock(BrightnessConfiguration.class), AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED); when(mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()).thenReturn( autoBrightnessAdjustment); diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java index ee79d196cfd9..5e240cf66674 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayObserverTest.java @@ -23,6 +23,7 @@ import static android.view.Display.Mode.INVALID_MODE_ID; import static com.android.server.display.mode.DisplayModeDirector.SYNCHRONIZED_REFRESH_RATE_TOLERANCE; import static com.android.server.display.mode.Vote.PRIORITY_LIMIT_MODE; import static com.android.server.display.mode.Vote.PRIORITY_SYNCHRONIZED_REFRESH_RATE; +import static com.android.server.display.mode.Vote.PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE; import static com.android.server.display.mode.Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE; import static com.android.server.display.mode.VotesStorage.GLOBAL_ID; @@ -360,16 +361,22 @@ public class DisplayObserverTest { .thenReturn(true); init(); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); mObserver.onDisplayAdded(EXTERNAL_DISPLAY); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo( Vote.forPhysicalRefreshRates( MAX_REFRESH_RATE - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, MAX_REFRESH_RATE + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo( + Vote.forRenderFrameRates( + MAX_REFRESH_RATE - SYNCHRONIZED_REFRESH_RATE_TOLERANCE, + MAX_REFRESH_RATE + SYNCHRONIZED_REFRESH_RATE_TOLERANCE)); // Remove external display and check that sync vote is no longer present. mObserver.onDisplayRemoved(EXTERNAL_DISPLAY); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); } /** External display added, disabled feature refresh rates synchronization */ @@ -383,8 +390,10 @@ public class DisplayObserverTest { .thenReturn(true); init(); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); mObserver.onDisplayAdded(EXTERNAL_DISPLAY); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); } /** External display not applied refresh rates synchronization, because @@ -397,8 +406,10 @@ public class DisplayObserverTest { when(mDisplayManagerFlags.isDisplaysRefreshRatesSynchronizationEnabled()).thenReturn(true); init(); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); mObserver.onDisplayAdded(EXTERNAL_DISPLAY); assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_REFRESH_RATE)).isEqualTo(null); + assertThat(getVote(GLOBAL_ID, PRIORITY_SYNCHRONIZED_RENDER_FRAME_RATE)).isEqualTo(null); } private void init() { diff --git a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java index d6c8ceb7ea6f..97c12bb6ef33 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.app.NotificationManager; +import android.os.UserHandle; import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; @@ -70,6 +71,8 @@ public class DisplayNotificationManagerTest { private ArgumentCaptor<Integer> mNotifyNoteIdCaptor; @Captor private ArgumentCaptor<Notification> mNotifyAsUserNotificationCaptor; + @Captor + private ArgumentCaptor<UserHandle> mNotifyAsUserCaptor; /** Setup tests. */ @Before @@ -127,7 +130,8 @@ public class DisplayNotificationManagerTest { dnm.onDisplayPortLinkTrainingFailure(); dnm.onCableNotCapableDisplayPort(); dnm.onHighTemperatureExternalDisplayNotAllowed(); - verify(mMockedNotificationManager, never()).notify(anyString(), anyInt(), any()); + verify(mMockedNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), + any()); } @Test @@ -175,10 +179,11 @@ public class DisplayNotificationManagerTest { } private void assertExpectedNotification() { - verify(mMockedNotificationManager).notify( + verify(mMockedNotificationManager).notifyAsUser( mNotifyTagCaptor.capture(), mNotifyNoteIdCaptor.capture(), - mNotifyAsUserNotificationCaptor.capture()); + mNotifyAsUserNotificationCaptor.capture(), + mNotifyAsUserCaptor.capture()); assertThat(mNotifyTagCaptor.getValue()).isEqualTo("DisplayNotificationManager"); assertThat((int) mNotifyNoteIdCaptor.getValue()).isEqualTo(1); final var notification = mNotifyAsUserNotificationCaptor.getValue(); @@ -188,5 +193,7 @@ public class DisplayNotificationManagerTest { assertThat(notification.flags & FLAG_ONGOING_EVENT).isEqualTo(0); assertThat(notification.when).isEqualTo(0); assertThat(notification.getTimeoutAfter()).isEqualTo(30000L); + final var user = mNotifyAsUserCaptor.getValue(); + assertThat(user).isEqualTo(UserHandle.CURRENT); } } diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java index b4e1abff3bf7..265b74dcee22 100644 --- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java +++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -215,4 +216,39 @@ public class DreamServiceTest { // Ensure service does not crash from only receiving up event. environment.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE)); } + + @Test + @EnableFlags(Flags.FLAG_DREAM_HANDLES_BEING_OBSCURED) + public void testComeToFront() throws Exception { + TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper) + .setDreamOverlayPresent(true) + .build(); + environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED); + + // Call comeToFront through binder. + environment.resetClientInvocations(); + environment.comeToFront(); + mTestableLooper.processAllMessages(); + + // Overlay client receives call. + verify(environment.getDreamOverlayClient()).comeToFront(); + } + + @Test + @EnableFlags(Flags.FLAG_DREAM_HANDLES_BEING_OBSCURED) + public void testComeToFront_noOverlay() throws Exception { + // Dream environment with no overlay present + TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper) + .setDreamOverlayPresent(false) + .build(); + environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED); + + // Call comeToFront through binder. + environment.resetClientInvocations(); + environment.comeToFront(); + mTestableLooper.processAllMessages(); + + // Overlay client receives call. + verify(environment.getDreamOverlayClient(), never()).comeToFront(); + } } diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java index e2b93ae3e9e7..43aa7fe46ca5 100644 --- a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java +++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java @@ -398,10 +398,14 @@ public class TestDreamEnvironment { mService.dispatchKeyEvent(event); } - private void wakeDream() throws RemoteException { + private void wakeDream() { mService.wakeUp(); } + void comeToFront() throws RemoteException { + mDreamServiceWrapper.comeToFront(); + } + /** * Retrieves the dream overlay callback. */ diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerGroupTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerGroupTest.java index 39def75e01be..473c8c5ce8fc 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/PowerGroupTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/PowerGroupTest.java @@ -79,8 +79,6 @@ public class PowerGroupTest { private static final float BRIGHTNESS = 0.99f; private static final float BRIGHTNESS_DOZE = 0.5f; - - private PowerGroup mPowerGroup; @Mock private PowerGroup.PowerGroupListener mWakefulnessCallbackMock; @Mock private Notifier mNotifier; @@ -264,6 +262,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -282,6 +281,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -289,7 +289,52 @@ public class PowerGroupTest { @Test public void testUpdateWhileDozing_UpdatesDisplayPowerRequest() { + final boolean useNormalBrightnessForDoze = false; + final boolean batterySaverEnabled = false; + float brightnessFactor = 0.3f; + PowerSaveState powerSaveState = new PowerSaveState.Builder() + .setBatterySaverEnabled(batterySaverEnabled) + .setBrightnessFactor(brightnessFactor) + .build(); + mPowerGroup.dozeLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_APPLICATION); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + mPowerGroup.setWakeLockSummaryLocked(WAKE_LOCK_DOZE); + + mPowerGroup.updateLocked(/* screenBrightnessOverride= */ BRIGHTNESS, + /* overrideTag= */ null, + /* useProximitySensor= */ true, + /* boostScreenBrightness= */ true, + /* dozeScreenStateOverride= */ Display.STATE_ON, + /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, + /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + useNormalBrightnessForDoze, + /* overrideDrawWakeLock= */ false, + powerSaveState, + /* quiescent= */ false, + /* dozeAfterScreenOff= */ false, + /* bootCompleted= */ true, + /* screenBrightnessBoostInProgress= */ false, + /* waitForNegativeProximity= */ false, + /* brightWhenDozing= */ false); + DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = + mPowerGroup.mDisplayPowerRequest; + assertThat(displayPowerRequest.policy).isEqualTo(POLICY_DOZE); + assertThat(displayPowerRequest.screenBrightnessOverride).isWithin(PRECISION).of(BRIGHTNESS); + assertThat(displayPowerRequest.useProximitySensor).isEqualTo(true); + assertThat(displayPowerRequest.boostScreenBrightness).isEqualTo(true); + assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_ON); + assertThat(displayPowerRequest.dozeScreenBrightness).isWithin(PRECISION).of( + BRIGHTNESS_DOZE); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); + assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); + assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( + brightnessFactor); + } + + @Test + public void testUpdateWhileDozing_useNormalBrightness() { final boolean batterySaverEnabled = false; + final boolean useNormalBrightnessForDoze = true; float brightnessFactor = 0.3f; PowerSaveState powerSaveState = new PowerSaveState.Builder() .setBatterySaverEnabled(batterySaverEnabled) @@ -306,6 +351,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + useNormalBrightnessForDoze, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -323,6 +369,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_ON); assertThat(displayPowerRequest.dozeScreenBrightness).isWithin(PRECISION).of( BRIGHTNESS_DOZE); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isTrue(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -346,6 +393,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -363,6 +411,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -385,6 +434,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ true, @@ -402,6 +452,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -424,6 +475,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -441,6 +493,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -464,6 +517,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -481,6 +535,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -502,6 +557,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -519,6 +575,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -541,6 +598,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -558,6 +616,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); @@ -579,6 +638,7 @@ public class PowerGroupTest { /* dozeScreenStateOverride= */ Display.STATE_ON, /* dozeScreenStateReason= */ Display.STATE_REASON_DEFAULT_POLICY, /* dozeScreenBrightness= */ BRIGHTNESS_DOZE, + /* useNormalBrightnessForDoze= */ false, /* overrideDrawWakeLock= */ false, powerSaveState, /* quiescent= */ false, @@ -596,6 +656,7 @@ public class PowerGroupTest { assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN); assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo( PowerManager.BRIGHTNESS_INVALID_FLOAT); + assertThat(displayPowerRequest.useNormalBrightnessForDoze).isFalse(); assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled); assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of( brightnessFactor); diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java index 40c521a1dc64..b58c28bfbe62 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java @@ -1305,7 +1305,8 @@ public class PowerManagerServiceTest { Display.STATE_ON, Display.STATE_REASON_DEFAULT_POLICY, PowerManager.BRIGHTNESS_INVALID_FLOAT, - PowerManager.BRIGHTNESS_DEFAULT); + PowerManager.BRIGHTNESS_DEFAULT, + /* useDozeBrightness= */ false); assertTrue(isAcquired[0]); } diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index a86289b317d0..701c3508be8a 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -272,6 +272,10 @@ java_genrule { "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res", } +FLAKY = [ + "androidx.test.filters.FlakyTest", +] + FLAKY_AND_IGNORED = [ "androidx.test.filters.FlakyTest", "org.junit.Ignore", @@ -328,7 +332,7 @@ test_module_config { base: "FrameworksServicesTests", test_suites: ["device-tests"], include_filters: ["com.android.server.recoverysystem."], - exclude_annotations: ["androidx.test.filters.FlakyTest"], + exclude_annotations: FLAKY, } // server pm TEST_MAPPING @@ -357,3 +361,319 @@ test_module_config { test_suites: ["device-tests"], include_filters: ["com.android.server.os."], } + +test_module_config { + name: "FrameworksServicesTests_presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_AND_IGNORED, +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_job_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.job"], + exclude_annotations: [ + "androidx.test.filters.LargeTest", + "androidx.test.filters.FlakyTest", + ], +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_job", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.job"], +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_tare_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.tare"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_tare", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.tare"], +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_usage_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.usage"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_usage", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.usage"], +} + +test_module_config { + name: "FrameworksServicesTests_battery_stats", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.am.BatteryStatsServiceTest"], +} + +test_module_config { + name: "FrameworksServicesTests_accessibility_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.accessibility"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_accessibility", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.accessibility"], +} + +test_module_config { + name: "FrameworksServicesTests_binary_transparency", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.BinaryTransparencyServiceTest"], +} + +test_module_config { + name: "FrameworksServicesTests_pinner_service", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.PinnerServiceTest"], + exclude_annotations: ["org.junit.Ignore"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_am_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.am."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_am", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.am."], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_appop", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.appop"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_audio", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.audio"], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_AND_IGNORED, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_compat", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.compat"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_hdmi_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.hdmi"], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_AND_IGNORED, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_hdmi", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.hdmi"], + exclude_annotations: ["org.junit.Ignore"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_integrity", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.integrity."], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_lights", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.lights"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_locales", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.locales."], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_location_contexthub_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.location.contexthub."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY_AND_IGNORED, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_locksettings", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.locksettings."], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_logcat_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.logcat"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_logcat", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.logcat"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_net_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.net."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_om", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.om."], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_pdb", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.pdb.PersistentDataBlockServiceTest"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_pm_dex", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.pm.dex"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_policy_Presubmit", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.policy."], + include_annotations: ["android.platform.test.annotations.Presubmit"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_policy", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.policy."], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_power", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.power"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_power_hint", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.power.hint"], + exclude_annotations: FLAKY, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_powerstats", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.powerstats"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_rollback", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.rollback"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_uri", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.uri."], +} + +test_module_config { + name: "FrameworksServicesTests_com_android_server_location_contexthub", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.location.contexthub."], + include_annotations: ["android.platform.test.annotations.Postsubmit"], + exclude_annotations: FLAKY_AND_IGNORED, +} + +test_module_config { + name: "FrameworksServicesTests_android_server_usage", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.usage"], + exclude_filters: ["com.android.server.usage.StorageStatsServiceTest"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_soundtrigger_middleware", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.soundtrigger_middleware"], +} + +test_module_config { + name: "FrameworksServicesTests_android_server_input", + base: "FrameworksServicesTests", + test_suites: ["device-tests"], + include_filters: ["com.android.server.input"], +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java index 3931580db47e..d80a1f056e94 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java @@ -18,13 +18,20 @@ package com.android.server.accessibility.magnification; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; +import static junit.framework.Assert.assertFalse; + import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.testng.AssertJUnit.assertTrue; import android.annotation.NonNull; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.view.InputDevice; import android.view.MotionEvent; @@ -32,8 +39,10 @@ import android.view.MotionEvent; import androidx.test.runner.AndroidJUnit4; import com.android.server.accessibility.AccessibilityTraceManager; +import com.android.server.accessibility.Flags; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -45,6 +54,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class MagnificationGestureHandlerTest { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + private TestMagnificationGestureHandler mMgh; private static final int DISPLAY_0 = 0; private static final int FULLSCREEN_MODE = @@ -81,6 +93,66 @@ public class MagnificationGestureHandlerTest { } @Test + @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) + public void onMotionEvent_isFromMouse_handleMouseOrStylusEvent() { + final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); + mouseEvent.setSource(InputDevice.SOURCE_MOUSE); + + mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); + + try { + assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); + } finally { + mouseEvent.recycle(); + } + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) + public void onMotionEvent_isFromStylus_handleMouseOrStylusEvent() { + final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); + stylusEvent.setSource(InputDevice.SOURCE_STYLUS); + + mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); + + try { + assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); + } finally { + stylusEvent.recycle(); + } + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) + public void onMotionEvent_isFromMouse_handleMouseOrStylusEventNotCalled() { + final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); + mouseEvent.setSource(InputDevice.SOURCE_MOUSE); + + mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); + + try { + assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); + } finally { + mouseEvent.recycle(); + } + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) + public void onMotionEvent_isFromStylus_handleMouseOrStylusEventNotCalled() { + final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); + stylusEvent.setSource(InputDevice.SOURCE_STYLUS); + + mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); + + try { + assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); + } finally { + stylusEvent.recycle(); + } + } + + @Test public void onMotionEvent_downEvent_handleInteractionStart() { final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); @@ -125,6 +197,7 @@ public class MagnificationGestureHandlerTest { private static class TestMagnificationGestureHandler extends MagnificationGestureHandler { boolean mIsInternalMethodCalled = false; + boolean mIsHandleMouseOrStylusEventCalled = false; TestMagnificationGestureHandler(int displayId, boolean detectSingleFingerTripleTap, boolean detectTwoFingerTripleTap, @@ -135,6 +208,11 @@ public class MagnificationGestureHandlerTest { } @Override + void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + mIsHandleMouseOrStylusEventCalled = true; + } + + @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mIsInternalMethodCalled = true; } diff --git a/services/tests/servicestests/src/com/android/server/autofill/PresentationEventLoggerTest.java b/services/tests/servicestests/src/com/android/server/autofill/PresentationEventLoggerTest.java new file mode 100644 index 000000000000..75258f0aa7e0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/autofill/PresentationEventLoggerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.autofill; + + +import static com.google.common.truth.Truth.assertThat; + +import android.view.autofill.AutofillId; +import android.view.autofill.AutofillValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class PresentationEventLoggerTest { + + @Test + public void testViewEntered() { + PresentationStatsEventLogger pEventLogger = + PresentationStatsEventLogger.createPresentationLog(1, 1, 1); + + AutofillId id = new AutofillId(13); + AutofillValue initialValue = AutofillValue.forText("hello"); + AutofillValue lastValue = AutofillValue.forText("hello world"); + ViewState vState = new ViewState(id, null, 0, false); + + pEventLogger.startNewEvent(); + pEventLogger.maybeSetFocusedId(id); + pEventLogger.onFieldTextUpdated(vState, initialValue); + pEventLogger.onFieldTextUpdated(vState, lastValue); + + PresentationStatsEventLogger.PresentationStatsEventInternal event = + pEventLogger.getInternalEvent().get(); + assertThat(event).isNotNull(); + assertThat(event.mFieldFirstLength).isEqualTo(initialValue.getTextValue().length()); + assertThat(event.mFieldLastLength).isEqualTo(lastValue.getTextValue().length()); + assertThat(event.mFieldModifiedFirstTimestampMs).isNotEqualTo(-1); + assertThat(event.mFieldModifiedLastTimestampMs).isNotEqualTo(-1); + } + + @Test + public void testViewAutofilled() { + PresentationStatsEventLogger pEventLogger = + PresentationStatsEventLogger.createPresentationLog(1, 1, 1); + + String newTextValue = "hello"; + AutofillValue value = AutofillValue.forText(newTextValue); + AutofillId id = new AutofillId(13); + ViewState vState = new ViewState(id, null, ViewState.STATE_AUTOFILLED, false); + + pEventLogger.startNewEvent(); + pEventLogger.maybeSetFocusedId(id); + pEventLogger.onFieldTextUpdated(vState, value); + + PresentationStatsEventLogger.PresentationStatsEventInternal event = + pEventLogger.getInternalEvent().get(); + assertThat(event).isNotNull(); + assertThat(event.mFieldFirstLength).isEqualTo(newTextValue.length()); + assertThat(event.mFieldLastLength).isEqualTo(newTextValue.length()); + assertThat(event.mAutofilledTimestampMs).isNotEqualTo(-1); + assertThat(event.mFieldModifiedFirstTimestampMs).isEqualTo(-1); + assertThat(event.mFieldModifiedLastTimestampMs).isEqualTo(-1); + } + + @Test + public void testModifiedOnDifferentView() { + PresentationStatsEventLogger pEventLogger = + PresentationStatsEventLogger.createPresentationLog(1, 1, 1); + + String newTextValue = "hello"; + AutofillValue value = AutofillValue.forText(newTextValue); + AutofillId id = new AutofillId(13); + ViewState vState = new ViewState(id, null, ViewState.STATE_AUTOFILLED, false); + + pEventLogger.startNewEvent(); + pEventLogger.onFieldTextUpdated(vState, value); + + PresentationStatsEventLogger.PresentationStatsEventInternal event = + pEventLogger.getInternalEvent().get(); + assertThat(event).isNotNull(); + assertThat(event.mFieldFirstLength).isEqualTo(-1); + assertThat(event.mFieldLastLength).isEqualTo(-1); + assertThat(event.mFieldModifiedFirstTimestampMs).isEqualTo(-1); + assertThat(event.mFieldModifiedLastTimestampMs).isEqualTo(-1); + assertThat(event.mAutofilledTimestampMs).isEqualTo(-1); + } + + @Test + public void testSetCountShown() { + PresentationStatsEventLogger pEventLogger = + PresentationStatsEventLogger.createPresentationLog(1, 1, 1); + + pEventLogger.startNewEvent(); + pEventLogger.logWhenDatasetShown(7); + + PresentationStatsEventLogger.PresentationStatsEventInternal event = + pEventLogger.getInternalEvent().get(); + assertThat(event).isNotNull(); + assertThat(event.mCountShown).isEqualTo(7); + assertThat(event.mNoPresentationReason) + .isEqualTo(PresentationStatsEventLogger.NOT_SHOWN_REASON_ANY_SHOWN); + } + + @Test + public void testFillDialogShownThenInline() { + PresentationStatsEventLogger pEventLogger = + PresentationStatsEventLogger.createPresentationLog(1, 1, 1); + + pEventLogger.startNewEvent(); + pEventLogger.maybeSetDisplayPresentationType(3); + pEventLogger.maybeSetDisplayPresentationType(2); + + PresentationStatsEventLogger.PresentationStatsEventInternal event = + pEventLogger.getInternalEvent().get(); + assertThat(event).isNotNull(); + assertThat(event.mDisplayPresentationType).isEqualTo(3); + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index a4222ff5650b..d2961bc8a90f 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -79,6 +79,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; @@ -1488,15 +1489,30 @@ public class BiometricServiceTest { } @Test + @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutTimed() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED); } @Test + @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutPermanent() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) + public void testCanAuthenticate_whenLockoutTimed_returnsLockoutError() throws Exception { + testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_TIMED); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) + public void testCanAuthenticate_whenLockoutPermanent_returnsLockoutError() throws Exception { + testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_PERMANENT); + } + + @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode) throws Exception { // When only biometric is requested, and sensor is strong enough @@ -1510,6 +1526,21 @@ public class BiometricServiceTest { invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); } + @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) + private void testCanAuthenticate_whenLockedOut_returnLockoutError( + @LockoutTracker.LockoutMode int lockoutMode) + throws Exception { + // When only biometric is requested, and sensor is strong enough + setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); + + when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) + .thenReturn(lockoutMode); + + // Lockout is not considered an error for BiometricManager#canAuthenticate + assertEquals(BiometricManager.BIOMETRIC_ERROR_LOCKOUT, + invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); + } + @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenMandatoryBiometricsRequested() @@ -1529,7 +1560,7 @@ public class BiometricServiceTest { when(mTrustManager.isInSignificantPlace()).thenReturn(true); - assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, + assertEquals(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); } @@ -1572,7 +1603,7 @@ public class BiometricServiceTest { setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL); - assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, + assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); when(mTrustManager.isInSignificantPlace()).thenReturn(true); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java index 240da9fe46bd..4c3a233fdd97 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java @@ -231,7 +231,7 @@ public class PreAuthInfoTest { @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) - public void testMandatoryBiometricsStatus_whenRequirementsNotSatisfiedAndSensorAvailable() + public void testMandatoryBiometricsAndStrongBiometricsStatus_whenRequirementsNotSatisfied() throws Exception { when(mTrustManager.isInSignificantPlace()).thenReturn(true); @@ -246,6 +246,24 @@ public class PreAuthInfoTest { assertThat(preAuthInfo.eligibleSensors).hasSize(1); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) + public void testMandatoryBiometricsStatus_whenRequirementsNotSatisfiedAndSensorAvailable() + throws Exception { + when(mTrustManager.isInSignificantPlace()).thenReturn(true); + + final BiometricSensor sensor = getFaceSensor(); + final PromptInfo promptInfo = new PromptInfo(); + promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS); + final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo( + BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE); + assertThat(preAuthInfo.eligibleSensors).hasSize(0); + } + private BiometricSensor getFingerprintSensor() { BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT, TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java index cb75e1ab6cce..14cb22d7698e 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java @@ -26,16 +26,25 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.PromptInfo; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import androidx.test.filters.SmallTest; +import org.junit.Rule; import org.junit.Test; @Presubmit @SmallTest public class UtilsTest { + @Rule + public final CheckFlagsRule mCheckFlagsRule = + DeviceFlagsValueProvider.createCheckFlagsRule(); @Test public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() { @@ -215,7 +224,8 @@ public class UtilsTest { } @Test - public void testBiometricConstantsConversion() { + @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) + public void testBiometricConstantsConversionLegacy() { final int[][] testCases = { {BiometricConstants.BIOMETRIC_SUCCESS, BiometricManager.BIOMETRIC_SUCCESS}, @@ -240,6 +250,34 @@ public class UtilsTest { } @Test + @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) + public void testBiometricConstantsConversion() { + final int[][] testCases = { + {BiometricConstants.BIOMETRIC_SUCCESS, + BiometricManager.BIOMETRIC_SUCCESS}, + {BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS, + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED}, + {BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL, + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED}, + {BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, + BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE}, + {BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT, + BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE}, + {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, + BiometricManager.BIOMETRIC_ERROR_LOCKOUT}, + {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, + BiometricManager.BIOMETRIC_ERROR_LOCKOUT}, + {BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE, + BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE} + }; + + for (int i = 0; i < testCases.length; i++) { + assertEquals(testCases[i][1], + Utils.biometricConstantsToBiometricManager(testCases[i][0])); + } + } + + @Test public void testGetAuthenticationTypeForResult_getsCorrectType() { assertEquals(Utils.getAuthenticationTypeForResult( BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED), diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java index 238a9289c05b..8f23ab99ba7f 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java @@ -236,6 +236,13 @@ public class BiometricLoggerTest { } @Test + public void testFingerprintsLoe() { + mLogger = createLogger(); + mLogger.logFingerprintsLoe(); + verify(mSink).reportFingerprintsLoe(eq(DEFAULT_MODALITY)); + } + + @Test public void testALSCallback() { mLogger = createLogger(); final CallbackWithProbe<Probe> callback = diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java index 242880ca49eb..7dcf8415f311 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java @@ -182,13 +182,22 @@ public class FingerprintInternalCleanupClientTest { public void invalidBiometricUserState() throws Exception { mClient = createClient(); + final List<Fingerprint> templates = List.of( + new Fingerprint("one", 1, 1), + new Fingerprint("two", 2, 1), + new Fingerprint("three", 3, 1) + ); + final List<Fingerprint> list = new ArrayList<>(); doReturn(true).when(mFingerprintUtils) .hasValidBiometricUserState(mContext, 2); doReturn(list).when(mFingerprintUtils).getBiometricsForUser(mContext, 2); mClient.start(mCallback); - mClient.onEnumerationResult(null, 0); + for (int i = templates.size() - 1; i >= 0; i--) { + mClient.getCurrentEnumerateClient().onEnumerationResult(templates.get(i), i); + } + verify(mLogger).logFingerprintsLoe(); verify(mFingerprintUtils).deleteStateForUser(2); } diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index c2882124e6e3..4d067f6bfc62 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -62,7 +62,6 @@ import android.companion.virtual.VirtualDeviceManager; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.audio.IAudioConfigChangedCallback; import android.companion.virtual.audio.IAudioRoutingCallback; -import android.companion.virtual.flags.Flags; import android.companion.virtual.sensor.VirtualSensor; import android.companion.virtual.sensor.VirtualSensorCallback; import android.companion.virtual.sensor.VirtualSensorConfig; @@ -1686,7 +1685,6 @@ public class VirtualDeviceManagerServiceTest { @Test public void openNonBlockedAppOnMirrorDisplay_flagEnabled_cannotBeLaunched() { - mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt())) .thenReturn(Display.DEFAULT_DISPLAY); addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); @@ -1711,31 +1709,6 @@ public class VirtualDeviceManagerServiceTest { } @Test - public void openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity() { - mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); - when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt())) - .thenReturn(Display.DEFAULT_DISPLAY); - addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); - GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( - DISPLAY_ID_1); - doNothing().when(mContext).startActivityAsUser(any(), any(), any()); - - ActivityInfo activityInfo = getActivityInfo( - NONBLOCKED_APP_PACKAGE_NAME, - NONBLOCKED_APP_PACKAGE_NAME, - /* displayOnRemoteDevices */ true, - /* targetDisplayCategory */ null); - assertThat(gwpc.canActivityBeLaunched(activityInfo, null, - WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false, - /* isResultExpected = */ false, /* intentSender= */ null)) - .isTrue(); - Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( - activityInfo, mAssociationInfo.getDisplayName()); - verify(mContext, never()).startActivityAsUser(argThat(intent -> - intent.filterEquals(blockedAppIntent)), any(), any()); - } - - @Test public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() { ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2)); addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS index 24561c59bba6..3d09da303b0f 100644 --- a/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS +++ b/services/tests/servicestests/src/com/android/server/contentprotection/OWNERS @@ -1,3 +1,4 @@ -# Bug component: 544200 +# Bug component: 1040349 + +include /core/java/android/view/contentprotection/OWNERS -include /core/java/android/view/contentcapture/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index e72d9e76e4e3..b7483d67563c 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -70,14 +70,14 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.longThat; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -1733,12 +1733,20 @@ public class DevicePolicyManagerTest extends DpmTestBase { pi.applicationInfo.flags = flags; doReturn(pi).when(getServices().ipackageManager).getPackageInfo( eq(packageName), - anyLong(), + longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) == 0), eq(userId)); + doReturn(pi).when(getServices().ipackageManager).getPackageInfo( + eq(packageName), + longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) != 0), + anyInt()); doReturn(pi.applicationInfo).when(getServices().ipackageManager).getApplicationInfo( eq(packageName), - anyLong(), + longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) == 0), eq(userId)); + doReturn(pi.applicationInfo).when(getServices().ipackageManager).getApplicationInfo( + eq(packageName), + longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) != 0), + anyInt()); doReturn(true).when(getServices().ipackageManager).isPackageAvailable(packageName, userId); // Setup application UID with the PackageManager getServices().addTestPackageUid(packageName, uid); @@ -1757,7 +1765,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mServiceContext.packageName = mRealTestContext.getPackageName(); mServiceContext.applicationInfo = new ApplicationInfo(); mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID; - when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE); + when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE); StringParceledListSlice oneCert = asSlice(new String[] {"1"}); StringParceledListSlice fourCerts = asSlice(new String[] {"1", "2", "3", "4"}); @@ -4551,7 +4559,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.packageName = admin1.getPackageName(); mContext.applicationInfo = new ApplicationInfo(); - when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE); + when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE); // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the // feature is disabled because there are non-affiliated secondary users. @@ -4597,12 +4605,12 @@ public class DevicePolicyManagerTest extends DpmTestBase { setupDeviceOwner(); mContext.packageName = admin1.getPackageName(); mContext.applicationInfo = new ApplicationInfo(); - when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE); + when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE); // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the // feature is disabled because there are non-affiliated secondary users. getServices().removeUser(CALLER_USER_HANDLE); - when(getServices().iipConnectivityMetrics.addNetdEventCallback(anyInt(), anyObject())) + when(getServices().iipConnectivityMetrics.addNetdEventCallback(anyInt(), any())) .thenReturn(true); // No logs were retrieved so far. @@ -4667,7 +4675,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.packageName = admin1.getPackageName(); addManagedProfile(admin1, managedProfileAdminUid, admin1, VERSION_CODES.S); when(getServices().iipConnectivityMetrics - .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); + .addNetdEventCallback(anyInt(), any())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); @@ -4699,7 +4707,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.packageName = admin1.getPackageName(); mContext.applicationInfo = new ApplicationInfo(); when(getServices().iipConnectivityMetrics - .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); + .addNetdEventCallback(anyInt(), any())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); @@ -6296,13 +6304,13 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpms.isNotificationListenerServicePermitted( - nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue(); + nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue(); assertThat(dpms.isNotificationListenerServicePermitted( - systemListener, MANAGED_PROFILE_USER_ID)).isTrue(); + systemListener, MANAGED_PROFILE_USER_ID)).isTrue(); assertThat(dpms.isNotificationListenerServicePermitted( - nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue(); + nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue(); assertThat(dpms.isNotificationListenerServicePermitted( - systemListener, UserHandle.USER_SYSTEM)).isTrue(); + systemListener, UserHandle.USER_SYSTEM)).isTrue(); // Setting an empty allowlist - only system listeners allowed in managed profile, but // all allowed in primary profile @@ -6313,13 +6321,13 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; assertThat(dpms.isNotificationListenerServicePermitted( - nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse(); + nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse(); assertThat(dpms.isNotificationListenerServicePermitted( - systemListener, MANAGED_PROFILE_USER_ID)).isTrue(); + systemListener, MANAGED_PROFILE_USER_ID)).isTrue(); assertThat(dpms.isNotificationListenerServicePermitted( - nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue(); + nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue(); assertThat(dpms.isNotificationListenerServicePermitted( - systemListener, UserHandle.USER_SYSTEM)).isTrue(); + systemListener, UserHandle.USER_SYSTEM)).isTrue(); } @Test @@ -6455,7 +6463,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { if (admin1.getPackageName().equals(callerContext.getPackageName())) { admin1Context = callerContext; } - when(admin1Context.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE); + when(admin1Context.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE); // caller: device admin or delegated certificate installer callerContext.applicationInfo = new ApplicationInfo(); @@ -6528,7 +6536,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { if (admin1.getPackageName().equals(callerContext.getPackageName())) { admin1Context = callerContext; } - when(admin1Context.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE); + when(admin1Context.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE); // caller: device admin or delegated certificate installer callerContext.applicationInfo = new ApplicationInfo(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java index 225c1dc752c1..51f64ba2b483 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java @@ -31,10 +31,11 @@ import static android.app.Notification.VISIBILITY_PUBLIC; import static android.app.Notification.VISIBILITY_SECRET; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION; import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING; +import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; -import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL; import static com.android.server.notification.GroupHelper.AGGREGATE_GROUP_KEY; import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY; import static com.android.server.notification.GroupHelper.BASE_FLAGS; @@ -2518,17 +2519,7 @@ public class GroupHelperTest extends UiServiceTestCase { assertThat(cachedSummary).isNull(); } - @Test - @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING) - public void testGroupSectioners() { - final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser, - "", false, IMPORTANCE_DEFAULT); - assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo("AlertingSection"); - - final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser, - "", false, IMPORTANCE_LOW); - assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection"); - + private void checkNonGroupableNotifications() { NotificationRecord notification_conversation = mock(NotificationRecord.class); when(notification_conversation.isConversation()).thenReturn(true); assertThat(GroupHelper.getSection(notification_conversation)).isNull(); @@ -2545,7 +2536,7 @@ public class GroupHelperTest extends UiServiceTestCase { assertThat(GroupHelper.getSection(notification_call)).isNull(); NotificationRecord notification_colorFg = spy(getNotificationRecord(mPkg, 0, "", mUser, - "", false, IMPORTANCE_LOW)); + "", false, IMPORTANCE_LOW)); sbn = spy(getSbn("package", 0, "0", UserHandle.SYSTEM)); n = mock(Notification.class); when(notification_colorFg.isConversation()).thenReturn(false); @@ -2558,4 +2549,97 @@ public class GroupHelperTest extends UiServiceTestCase { assertThat(GroupHelper.getSection(notification_colorFg)).isNull(); } + @Test + @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING) + @DisableFlags(FLAG_NOTIFICATION_CLASSIFICATION) + public void testGroupSectioners() { + final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser, + "", false, IMPORTANCE_DEFAULT); + assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo( + "AlertingSection"); + + final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser, + "", false, IMPORTANCE_LOW); + assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection"); + + // Check that special categories are grouped by their importance + final NotificationChannel promoChannel = new NotificationChannel( + NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID, + IMPORTANCE_DEFAULT); + final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser, + "", false, promoChannel); + assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo( + "AlertingSection"); + + final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID, + NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT); + final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser, + "", false, newsChannel); + assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo( + "AlertingSection"); + + final NotificationChannel socialChannel = new NotificationChannel( + NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID, + IMPORTANCE_DEFAULT); + final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser, + "", false, socialChannel); + assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo( + "AlertingSection"); + + final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID, + NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT); + final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser, + "", false, recsChannel); + assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo( + "AlertingSection"); + + checkNonGroupableNotifications(); + } + + @Test + @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_CLASSIFICATION}) + public void testGroupSectioners_withClassificationSections() { + final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser, + "", false, IMPORTANCE_DEFAULT); + assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo( + "AlertingSection"); + + final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser, + "", false, IMPORTANCE_LOW); + assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection"); + + // Check that special categories are grouped in their own sections + final NotificationChannel promoChannel = new NotificationChannel( + NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID, + IMPORTANCE_DEFAULT); + final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser, + "", false, promoChannel); + assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo( + "PromotionsSection"); + + final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID, + NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT); + final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser, + "", false, newsChannel); + assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo( + "NewsSection"); + + final NotificationChannel socialChannel = new NotificationChannel( + NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID, + IMPORTANCE_DEFAULT); + final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser, + "", false, socialChannel); + assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo( + "SocialSection"); + + final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID, + NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT); + final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser, + "", false, recsChannel); + assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo( + "RecsSection"); + + checkNonGroupableNotifications(); + } + } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java index 643ee4aadd80..62e5b9a3dccc 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java @@ -2007,6 +2007,25 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { } @Test + public void testCanInterruptNonRingtoneInsistentBuzzWithOtherBuzzyNotification() { + NotificationRecord r = getInsistentBuzzyNotification(); + mAttentionHelper.buzzBeepBlinkLocked(r, DEFAULT_SIGNALS); + verifyVibrateLooped(); + assertTrue(r.isInterruptive()); + assertNotEquals(-1, r.getLastAudiblyAlertedMs()); + Mockito.reset(mVibrator); + + // New buzzy notification stops previous looping vibration + NotificationRecord interrupter = getBuzzyOtherNotification(); + mAttentionHelper.buzzBeepBlinkLocked(interrupter, DEFAULT_SIGNALS); + verifyStopVibrate(); + // And then vibrates itself + verifyVibrate(1); + assertTrue(interrupter.isInterruptive()); + assertNotEquals(-1, interrupter.getLastAudiblyAlertedMs()); + } + + @Test public void testRingtoneInsistentBeep_doesNotBlockFutureSoundsOnceStopped() throws Exception { NotificationChannel ringtoneChannel = new NotificationChannel("ringtone", "", IMPORTANCE_HIGH); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java index 240bd1ec56e3..8797e63dab27 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java @@ -16,8 +16,6 @@ package com.android.server.vibrator; -import static android.os.VibrationAttributes.CATEGORY_KEYBOARD; -import static android.os.VibrationAttributes.CATEGORY_UNKNOWN; import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; @@ -255,7 +253,7 @@ public class HapticFeedbackVibrationProviderTest { } @Test - public void testKeyboardHaptic_fixAmplitude_keyboardCategoryOn_keyboardVibrationReturned() { + public void testKeyboardHaptic_fixAmplitude_keyboardVibrationReturned() { mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK); mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE); @@ -330,7 +328,7 @@ public class HapticFeedbackVibrationProviderTest { } @Test - public void testVibrationAttribute_keyboardCategoryOn_notIme_useTouchUsage() { + public void testVibrationAttribute_notIme_useTouchUsage() { HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { @@ -338,13 +336,11 @@ public class HapticFeedbackVibrationProviderTest { effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); - assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId) - .that(attrs.getCategory()).isEqualTo(CATEGORY_UNKNOWN); } } @Test - public void testVibrationAttribute_keyboardCategoryOn_isIme_useImeFeedbackUsage() { + public void testVibrationAttribute_isIme_useImeFeedbackUsage() { HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations(); for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { @@ -353,8 +349,6 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); assertWithMessage("Expected USAGE_IME_FEEDBACK for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_IME_FEEDBACK); - assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId) - .that(attrs.getCategory()).isEqualTo(CATEGORY_KEYBOARD); } } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java index 470469114dfa..9681d74eb9b3 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java @@ -281,8 +281,8 @@ public class VibrationScalerTest { @Test @EnableFlags(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) - public void scale_withVendorEffect_setsEffectStrengthBasedOnSettings() { - setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_LOW); + public void scale_withVendorEffect_setsEffectStrengthAndScaleBasedOnSettings() { + setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_MEDIUM); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); PersistableBundle vendorData = new PersistableBundle(); vendorData.putString("key", "value"); @@ -291,20 +291,27 @@ public class VibrationScalerTest { VibrationEffect.VendorEffect scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG); + // Notification scales up. + assertTrue(scaled.getScale() > 1); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_MEDIUM); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM); + // Notification does not scale. + assertEquals(1, scaled.getScale(), TOLERANCE); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT); + // Notification scales down. + assertTrue(scaled.getScale() < 1); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_NOTIFICATION); // Vibration setting being bypassed will use default setting. - assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT); + assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM); + assertEquals(1, scaled.getScale(), TOLERANCE); } @Test @@ -348,7 +355,7 @@ public class VibrationScalerTest { scaled = getFirstSegment(mVibrationScaler.scale(VibrationEffect.createOneShot(128, 128), USAGE_TOUCH)); // Haptic feedback does not scale. - assertEquals(128f / 255, scaled.getAmplitude(), 1e-5); + assertEquals(128f / 255, scaled.getAmplitude(), TOLERANCE); } @Test @@ -373,7 +380,7 @@ public class VibrationScalerTest { scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_TOUCH)); // Haptic feedback does not scale. - assertEquals(0.5, scaled.getScale(), 1e-5); + assertEquals(0.5, scaled.getScale(), TOLERANCE); } @Test @@ -446,7 +453,7 @@ public class VibrationScalerTest { android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED, android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS, }) - public void scale_adaptiveHapticsOnVendorEffect_setsLinearScaleParameter() { + public void scale_adaptiveHapticsOnVendorEffect_setsAdaptiveScaleParameter() { setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH); mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.5f); @@ -457,12 +464,12 @@ public class VibrationScalerTest { VibrationEffect.VendorEffect scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_RINGTONE); - assertEquals(scaled.getLinearScale(), 0.5f); + assertEquals(scaled.getAdaptiveScale(), 0.5f); mVibrationScaler.removeAdaptiveHapticsScale(USAGE_RINGTONE); scaled = (VibrationEffect.VendorEffect) mVibrationScaler.scale(effect, USAGE_RINGTONE); - assertEquals(scaled.getLinearScale(), 1.0f); + assertEquals(scaled.getAdaptiveScale(), 1.0f); } private void setDefaultIntensity(@VibrationAttributes.Usage int usage, diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java index 6f06050f55ff..38cd49daf99d 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -610,7 +610,6 @@ public class VibrationSettingsTest { assertVibrationIgnoredForAttributes( new VibrationAttributes.Builder() .setUsage(USAGE_IME_FEEDBACK) - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .build(), Vibration.Status.IGNORED_FOR_SETTINGS); @@ -619,7 +618,6 @@ public class VibrationSettingsTest { assertVibrationNotIgnoredForAttributes( new VibrationAttributes.Builder() .setUsage(USAGE_IME_FEEDBACK) - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF) .build()); } @@ -637,7 +635,6 @@ public class VibrationSettingsTest { assertVibrationNotIgnoredForAttributes( new VibrationAttributes.Builder() .setUsage(USAGE_IME_FEEDBACK) - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .build()); } @@ -654,7 +651,6 @@ public class VibrationSettingsTest { assertVibrationIgnoredForAttributes( new VibrationAttributes.Builder() .setUsage(USAGE_IME_FEEDBACK) - .setCategory(VibrationAttributes.CATEGORY_KEYBOARD) .build(), Vibration.Status.IGNORED_FOR_SETTINGS); } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java index 0fbdce4ce61a..bfdaa785a669 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java @@ -34,13 +34,15 @@ import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; -import android.content.Context; +import android.content.ContentResolver; +import android.content.ContextWrapper; import android.content.pm.PackageManagerInternal; import android.hardware.vibrator.Braking; import android.hardware.vibrator.IVibrator; @@ -52,6 +54,7 @@ import android.os.PersistableBundle; import android.os.PowerManager; import android.os.Process; import android.os.SystemClock; +import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; @@ -66,11 +69,14 @@ import android.os.vibrator.VibrationEffectSegment; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.provider.Settings; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; +import com.android.internal.util.test.FakeSettingsProvider; +import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.server.LocalServices; import org.junit.After; @@ -105,10 +111,12 @@ public class VibrationThreadTest { private static final int TEST_DEFAULT_AMPLITUDE = 255; private static final float TEST_DEFAULT_SCALE_LEVEL_GAIN = 1.4f; - @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule - public final CheckFlagsRule mCheckFlagsRule = - DeviceFlagsValueProvider.createCheckFlagsRule(); + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Rule + public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); @Mock private PackageManagerInternal mPackageManagerInternalMock; @Mock private VibrationThread.VibratorManagerHooks mManagerHooks; @@ -117,6 +125,7 @@ public class VibrationThreadTest { @Mock private VibrationConfig mVibrationConfigMock; @Mock private VibratorFrameworkStatsLogger mStatsLoggerMock; + private ContextWrapper mContextSpy; private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>(); private VibrationSettings mVibrationSettings; private VibrationScaler mVibrationScaler; @@ -149,14 +158,16 @@ public class VibrationThreadTest { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock); - Context context = InstrumentationRegistry.getContext(); - mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()), - mVibrationConfigMock); + mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); + ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); + when(mContextSpy.getContentResolver()).thenReturn(contentResolver); + mVibrationSettings = new VibrationSettings(mContextSpy, + new Handler(mTestLooper.getLooper()), mVibrationConfigMock); mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); mockVibrators(VIBRATOR_ID); - PowerManager.WakeLock wakeLock = context.getSystemService( + PowerManager.WakeLock wakeLock = mContextSpy.getSystemService( PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); mThread = new VibrationThread(wakeLock, mManagerHooks); mThread.start(); @@ -254,6 +265,9 @@ public class VibrationThreadTest { @Test @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void vibrate_singleWaveformWithAdaptiveHapticsScaling_scalesAmplitudesProperly() { + // No user settings scale. + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibrationEffect effect = VibrationEffect.createWaveform( @@ -277,6 +291,9 @@ public class VibrationThreadTest { @Test @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void vibrate_withVibrationParamsRequestStalling_timeoutRequestAndApplyNoScaling() { + // No user settings scale. + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, + Vibrator.VIBRATION_INTENSITY_MEDIUM); mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibrationEffect effect = VibrationEffect.createWaveform( new long[]{5, 5, 5}, new int[]{1, 1, 1}, -1); @@ -1864,6 +1881,13 @@ public class VibrationThreadTest { } } + private void setUserSetting(String settingName, int value) { + Settings.System.putIntForUser( + mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT); + // FakeSettingsProvider doesn't support testing triggering ContentObserver yet. + mVibrationSettings.mSettingObserver.onChange(false); + } + private long startThreadAndDispatcher(VibrationEffect effect) { return startThreadAndDispatcher(CombinedVibration.createParallel(effect)); } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index f009229e216d..40135876303b 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -1622,7 +1622,12 @@ public class VibratorManagerServiceTest { vibrateAndWaitUntilFinished(service, vendorEffect, RINGTONE_ATTRS); - assertThat(fakeVibrator.getAllVendorEffects()).containsExactly(vendorEffect); + // Compare vendor data only, ignore scale applied by device settings in this test. + assertThat(fakeVibrator.getAllVendorEffects()).hasSize(1); + assertThat(fakeVibrator.getAllVendorEffects().get(0).getVendorData().keySet()) + .containsExactly("key"); + assertThat(fakeVibrator.getAllVendorEffects().get(0).getVendorData().getString("key")) + .isEqualTo("value"); } @Test @@ -1765,7 +1770,8 @@ public class VibratorManagerServiceTest { assertThat(fakeVibrator.getAllVendorEffects()).hasSize(1); VibrationEffect.VendorEffect scaled = fakeVibrator.getAllVendorEffects().get(0); assertThat(scaled.getEffectStrength()).isEqualTo(VibrationEffect.EFFECT_STRENGTH_LIGHT); - assertThat(scaled.getLinearScale()).isEqualTo(0.4f); + assertThat(scaled.getScale()).isAtMost(1); // Scale down or none if default is LOW + assertThat(scaled.getAdaptiveScale()).isEqualTo(0.4f); } @Test diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java index 96c3e97bc819..031d1c29a215 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java @@ -140,13 +140,13 @@ public final class FakeVibratorControllerProvider { @Override public long performVendorEffect(Parcel vendorData, long strength, float scale, - long vibrationId) { + float adaptiveScale, long vibrationId) { if ((mCapabilities & IVibrator.CAP_PERFORM_VENDOR_EFFECTS) == 0) { return 0; } PersistableBundle bundle = PersistableBundle.CREATOR.createFromParcel(vendorData); recordVendorEffect(vibrationId, - new VibrationEffect.VendorEffect(bundle, (int) strength, scale)); + new VibrationEffect.VendorEffect(bundle, (int) strength, scale, adaptiveScale)); applyLatency(mOnLatency); scheduleListener(mVendorEffectDuration, vibrationId); // HAL has unknown duration for vendor effects. diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index 6ba2c7010cf3..604869c7f0ca 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -57,6 +57,7 @@ android_test { "service-permission.stubs.system_server", "androidx.test.runner", "androidx.test.rules", + "flickerlib", "junit-params", "mockito-target-extended-minus-junit4", "platform-test-annotations", diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java index e26f3e0f699a..8f3adba81be4 100644 --- a/services/tests/wmtests/src/com/android/server/policy/KeyboardSystemShortcutTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java @@ -22,7 +22,7 @@ import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_ASSIS import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_HOME_NOTIFICATION_PANEL; import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL; -import android.hardware.input.KeyboardSystemShortcut; +import android.hardware.input.KeyGestureEvent; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; @@ -44,7 +44,7 @@ import org.junit.runner.RunWith; @Presubmit @MediumTest @RunWith(JUnitParamsRunner.class) -public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase { +public class KeyGestureEventTests extends ShortcutKeyTestBase { @Rule public final CheckFlagsRule mCheckFlagsRule = @@ -56,315 +56,313 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase { private static final int ALT_ON = MODIFIER.get(KeyEvent.KEYCODE_ALT_LEFT); private static final int CTRL_KEY = KeyEvent.KEYCODE_CTRL_LEFT; private static final int CTRL_ON = MODIFIER.get(KeyEvent.KEYCODE_CTRL_LEFT); - private static final int SHIFT_KEY = KeyEvent.KEYCODE_SHIFT_LEFT; - private static final int SHIFT_ON = MODIFIER.get(KeyEvent.KEYCODE_SHIFT_LEFT); @Keep private static Object[][] shortcutTestArguments() { - // testName, testKeys, expectedSystemShortcut, expectedKey, expectedModifierState + // testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState return new Object[][]{ {"Meta + H -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_H}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_H, META_ON}, + KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_H, META_ON}, {"Meta + Enter -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, KeyEvent.KEYCODE_ENTER, + KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_ENTER, META_ON}, {"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME, + KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_HOME, 0}, {"RECENT_APPS key -> Open Overview", new int[]{KeyEvent.KEYCODE_RECENT_APPS}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_RECENT_APPS, 0}, {"Meta + Tab -> Open Overview", new int[]{META_KEY, KeyEvent.KEYCODE_TAB}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_TAB, META_ON}, {"Alt + Tab -> Open Overview", new int[]{ALT_KEY, KeyEvent.KEYCODE_TAB}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_RECENT_APPS, KeyEvent.KEYCODE_TAB, + KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_TAB, ALT_ON}, {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_BACK, 0}, {"Meta + Escape -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_ESCAPE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_ESCAPE, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_ESCAPE, META_ON}, {"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DPAD_LEFT, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_DPAD_LEFT, META_ON}, {"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BACK, KeyEvent.KEYCODE_DEL, META_ON}, + KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_DEL, META_ON}, {"APP_SWITCH key -> Open App switcher", new int[]{KeyEvent.KEYCODE_APP_SWITCH}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_APP_SWITCH, 0}, {"ASSIST key -> Launch assistant", new int[]{KeyEvent.KEYCODE_ASSIST}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_ASSIST, 0}, {"Meta + A -> Launch assistant", new int[]{META_KEY, KeyEvent.KEYCODE_A}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_A, META_ON}, {"VOICE_ASSIST key -> Launch Voice Assistant", new int[]{KeyEvent.KEYCODE_VOICE_ASSIST}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_VOICE_ASSISTANT, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT, KeyEvent.KEYCODE_VOICE_ASSIST, 0}, {"Meta + I -> Launch System Settings", new int[]{META_KEY, KeyEvent.KEYCODE_I}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SYSTEM_SETTINGS, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS, KeyEvent.KEYCODE_I, META_ON}, {"Meta + N -> Toggle Notification panel", new int[]{META_KEY, KeyEvent.KEYCODE_N}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_N, META_ON}, {"NOTIFICATION key -> Toggle Notification Panel", new int[]{KeyEvent.KEYCODE_NOTIFICATION}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_NOTIFICATION, 0}, {"Meta + Ctrl + S -> Take Screenshot", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_S}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S, + KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT, KeyEvent.KEYCODE_S, META_ON | CTRL_ON}, {"Meta + / -> Open Shortcut Helper", new int[]{META_KEY, KeyEvent.KEYCODE_SLASH}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_SHORTCUT_HELPER, + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER, KeyEvent.KEYCODE_SLASH, META_ON}, {"BRIGHTNESS_UP key -> Increase Brightness", new int[]{KeyEvent.KEYCODE_BRIGHTNESS_UP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_UP, + KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP, KeyEvent.KEYCODE_BRIGHTNESS_UP, 0}, {"BRIGHTNESS_DOWN key -> Decrease Brightness", new int[]{KeyEvent.KEYCODE_BRIGHTNESS_DOWN}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_BRIGHTNESS_DOWN, + KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN, KeyEvent.KEYCODE_BRIGHTNESS_DOWN, 0}, {"KEYBOARD_BACKLIGHT_UP key -> Increase Keyboard Backlight", new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_UP, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP, KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP, 0}, {"KEYBOARD_BACKLIGHT_DOWN key -> Decrease Keyboard Backlight", new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_DOWN, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN, KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN, 0}, {"KEYBOARD_BACKLIGHT_TOGGLE key -> Toggle Keyboard Backlight", new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_KEYBOARD_BACKLIGHT_TOGGLE, + KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE, KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE, 0}, {"VOLUME_UP key -> Increase Volume", new int[]{KeyEvent.KEYCODE_VOLUME_UP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_UP, + KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_UP, 0}, {"VOLUME_DOWN key -> Decrease Volume", new int[]{KeyEvent.KEYCODE_VOLUME_DOWN}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_DOWN, + KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN, 0}, {"VOLUME_MUTE key -> Mute Volume", new int[]{KeyEvent.KEYCODE_VOLUME_MUTE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_VOLUME_MUTE, + KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE, KeyEvent.KEYCODE_VOLUME_MUTE, 0}, {"ALL_APPS key -> Open App Drawer in Accessibility mode", new int[]{KeyEvent.KEYCODE_ALL_APPS}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_ALL_APPS, 0}, {"SEARCH key -> Launch Search Activity", new int[]{KeyEvent.KEYCODE_SEARCH}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_SEARCH, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH, KeyEvent.KEYCODE_SEARCH, 0}, {"LANGUAGE_SWITCH key -> Switch Keyboard Language", new int[]{KeyEvent.KEYCODE_LANGUAGE_SWITCH}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LANGUAGE_SWITCH, + KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH, KeyEvent.KEYCODE_LANGUAGE_SWITCH, 0}, {"META key -> Open App Drawer in Accessibility mode", new int[]{META_KEY}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, META_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, META_KEY, META_ON}, {"Meta + Alt -> Toggle CapsLock", new int[]{META_KEY, ALT_KEY}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, ALT_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, ALT_KEY, META_ON | ALT_ON}, {"Alt + Meta -> Toggle CapsLock", new int[]{ALT_KEY, META_KEY}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, META_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, META_KEY, META_ON | ALT_ON}, {"CAPS_LOCK key -> Toggle CapsLock", new int[]{KeyEvent.KEYCODE_CAPS_LOCK}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_CAPS_LOCK, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK, KeyEvent.KEYCODE_CAPS_LOCK, 0}, {"MUTE key -> Mute System Microphone", new int[]{KeyEvent.KEYCODE_MUTE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE, 0}, {"Meta + Ctrl + DPAD_UP -> Split screen navigation", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_UP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MULTI_WINDOW_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION, KeyEvent.KEYCODE_DPAD_UP, META_ON | CTRL_ON}, {"Meta + Ctrl + DPAD_LEFT -> Split screen navigation", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_LEFT}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_LEFT, META_ON | CTRL_ON}, {"Meta + Ctrl + DPAD_RIGHT -> Split screen navigation", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_RIGHT}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SPLIT_SCREEN_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_RIGHT, META_ON | CTRL_ON}, {"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LOCK_SCREEN, KeyEvent.KEYCODE_L, + KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN, KeyEvent.KEYCODE_L, META_ON}, {"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_OPEN_NOTES, KeyEvent.KEYCODE_N, + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, KeyEvent.KEYCODE_N, META_ON | CTRL_ON}, {"POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_POWER}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER, KeyEvent.KEYCODE_POWER, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER, KeyEvent.KEYCODE_POWER, 0}, {"TV_POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_TV_POWER}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_POWER, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER, KeyEvent.KEYCODE_TV_POWER, 0}, {"SYSTEM_NAVIGATION_DOWN key -> System Navigation", new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN, 0}, {"SYSTEM_NAVIGATION_UP key -> System Navigation", new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP, 0}, {"SYSTEM_NAVIGATION_LEFT key -> System Navigation", new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT, 0}, {"SYSTEM_NAVIGATION_RIGHT key -> System Navigation", new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SYSTEM_NAVIGATION, + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT, 0}, {"SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SLEEP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SLEEP, 0}, + KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SLEEP, 0}, {"SOFT_SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SOFT_SLEEP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP, + KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP, 0}, {"WAKEUP key -> System Wakeup", new int[]{KeyEvent.KEYCODE_WAKEUP}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0}, + KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0}, {"MEDIA_PLAY key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY, KeyEvent.KEYCODE_MEDIA_PLAY, 0}, {"MEDIA_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PAUSE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY, KeyEvent.KEYCODE_MEDIA_PAUSE, 0}, {"MEDIA_PLAY_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_MEDIA_KEY, + KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0}, {"Meta + B -> Launch Default Browser", new int[]{META_KEY, KeyEvent.KEYCODE_B}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER, KeyEvent.KEYCODE_B, META_ON}, {"EXPLORER key -> Launch Default Browser", new int[]{KeyEvent.KEYCODE_EXPLORER}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_BROWSER, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER, KeyEvent.KEYCODE_EXPLORER, 0}, {"Meta + C -> Launch Default Contacts", new int[]{META_KEY, KeyEvent.KEYCODE_C}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS, KeyEvent.KEYCODE_C, META_ON}, {"CONTACTS key -> Launch Default Contacts", new int[]{KeyEvent.KEYCODE_CONTACTS}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CONTACTS, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS, KeyEvent.KEYCODE_CONTACTS, 0}, {"Meta + E -> Launch Default Email", new int[]{META_KEY, KeyEvent.KEYCODE_E}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL, KeyEvent.KEYCODE_E, META_ON}, {"ENVELOPE key -> Launch Default Email", new int[]{KeyEvent.KEYCODE_ENVELOPE}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_EMAIL, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL, KeyEvent.KEYCODE_ENVELOPE, 0}, {"Meta + K -> Launch Default Calendar", new int[]{META_KEY, KeyEvent.KEYCODE_K}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR, KeyEvent.KEYCODE_K, META_ON}, {"CALENDAR key -> Launch Default Calendar", new int[]{KeyEvent.KEYCODE_CALENDAR}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALENDAR, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR, KeyEvent.KEYCODE_CALENDAR, 0}, {"Meta + P -> Launch Default Music", new int[]{META_KEY, KeyEvent.KEYCODE_P}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC, KeyEvent.KEYCODE_P, META_ON}, {"MUSIC key -> Launch Default Music", new int[]{KeyEvent.KEYCODE_MUSIC}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MUSIC, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC, KeyEvent.KEYCODE_MUSIC, 0}, {"Meta + U -> Launch Default Calculator", new int[]{META_KEY, KeyEvent.KEYCODE_U}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR, KeyEvent.KEYCODE_U, META_ON}, {"CALCULATOR key -> Launch Default Calculator", new int[]{KeyEvent.KEYCODE_CALCULATOR}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_CALCULATOR, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR, KeyEvent.KEYCODE_CALCULATOR, 0}, {"Meta + M -> Launch Default Maps", new int[]{META_KEY, KeyEvent.KEYCODE_M}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MAPS, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS, KeyEvent.KEYCODE_M, META_ON}, {"Meta + S -> Launch Default Messaging App", new int[]{META_KEY, KeyEvent.KEYCODE_S}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_DEFAULT_MESSAGING, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING, KeyEvent.KEYCODE_S, META_ON}, {"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_DESKTOP_MODE, + KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE, KeyEvent.KEYCODE_DPAD_DOWN, META_ON | CTRL_ON}}; } @Keep private static Object[][] longPressOnHomeTestArguments() { - // testName, testKeys, longPressOnHomeBehavior, expectedSystemShortcut, expectedKey, + // testName, testKeys, longPressOnHomeBehavior, expectedKeyGestureType, expectedKey, // expectedModifierState return new Object[][]{ {"Long press HOME key -> Toggle Notification panel", new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_NOTIFICATION_PANEL, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_HOME, 0}, {"Long press META + ENTER -> Toggle Notification panel", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_NOTIFICATION_PANEL, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_ENTER, META_ON}, {"Long press META + H -> Toggle Notification panel", new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_NOTIFICATION_PANEL, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_H, META_ON}, {"Long press HOME key -> Launch assistant", new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ASSIST, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_HOME, 0}, {"Long press META + ENTER -> Launch assistant", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ASSIST, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_ENTER, META_ON}, {"Long press META + H -> Launch assistant", new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_ASSIST, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H, + KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H, META_ON}, {"Long press HOME key -> Open App Drawer in Accessibility mode", new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ALL_APPS, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_HOME, 0}, {"Long press META + ENTER -> Open App Drawer in Accessibility mode", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ALL_APPS, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_ENTER, META_ON}, {"Long press META + H -> Open App Drawer in Accessibility mode", new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_ALL_APPS, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_ACCESSIBILITY_ALL_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, KeyEvent.KEYCODE_H, META_ON}}; } @Keep private static Object[][] doubleTapOnHomeTestArguments() { - // testName, testKeys, doubleTapOnHomeBehavior, expectedSystemShortcut, expectedKey, + // testName, testKeys, doubleTapOnHomeBehavior, expectedKeyGestureType, expectedKey, // expectedModifierState return new Object[][]{ {"Double tap HOME -> Open App switcher", new int[]{KeyEvent.KEYCODE_HOME}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_HOME, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_HOME, 0}, {"Double tap META + ENTER -> Open App switcher", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_ENTER, META_ON}, {"Double tap META + H -> Open App switcher", new int[]{META_KEY, KeyEvent.KEYCODE_H}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_APP_SWITCH, KeyEvent.KEYCODE_H, + KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_H, META_ON}}; } @Keep private static Object[][] settingsKeyTestArguments() { - // testName, testKeys, settingsKeyBehavior, expectedSystemShortcut, expectedKey, + // testName, testKeys, settingsKeyBehavior, expectedKeyGestureType, expectedKey, // expectedModifierState return new Object[][]{ {"SETTINGS key -> Toggle Notification panel", new int[]{KeyEvent.KEYCODE_SETTINGS}, SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TOGGLE_NOTIFICATION_PANEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL, KeyEvent.KEYCODE_SETTINGS, 0}}; } @@ -387,21 +385,21 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase { @Test @Parameters(method = "shortcutTestArguments") public void testShortcut(String testName, int[] testKeys, - @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey, + @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { - testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey, + testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState); } @Test @Parameters(method = "longPressOnHomeTestArguments") public void testLongPressOnHome(String testName, int[] testKeys, int longPressOnHomeBehavior, - @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey, + @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { mPhoneWindowManager.overrideLongPressOnHomeBehavior(longPressOnHomeBehavior); sendLongPressKeyCombination(testKeys); - mPhoneWindowManager.assertKeyboardShortcutTriggered( - new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut, + mPhoneWindowManager.assertKeyGestureCompleted( + new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType, "Failed while executing " + testName); } @@ -409,23 +407,23 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase { @Parameters(method = "doubleTapOnHomeTestArguments") public void testDoubleTapOnHomeBehavior(String testName, int[] testKeys, int doubleTapOnHomeBehavior, - @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey, + @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { mPhoneWindowManager.overriderDoubleTapOnHomeBehavior(doubleTapOnHomeBehavior); sendKeyCombination(testKeys, 0 /* duration */); sendKeyCombination(testKeys, 0 /* duration */); - mPhoneWindowManager.assertKeyboardShortcutTriggered( - new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut, + mPhoneWindowManager.assertKeyGestureCompleted( + new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType, "Failed while executing " + testName); } @Test @Parameters(method = "settingsKeyTestArguments") public void testSettingsKey(String testName, int[] testKeys, int settingsKeyBehavior, - @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey, + @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { mPhoneWindowManager.overrideSettingsKeyBehavior(settingsKeyBehavior); - testShortcutInternal(testName, testKeys, expectedSystemShortcut, expectedKey, + testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState); } @@ -434,16 +432,16 @@ public class KeyboardSystemShortcutTests extends ShortcutKeyTestBase { public void testBugreportShortcutPress() { testShortcutInternal("Meta + Ctrl + Del -> Trigger bug report", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL}, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL, + KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL, META_ON | CTRL_ON); } private void testShortcutInternal(String testName, int[] testKeys, - @KeyboardSystemShortcut.SystemShortcut int expectedSystemShortcut, int expectedKey, + @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { sendKeyCombination(testKeys, 0 /* duration */); - mPhoneWindowManager.assertKeyboardShortcutTriggered( - new int[]{expectedKey}, expectedModifierState, expectedSystemShortcut, + mPhoneWindowManager.assertKeyGestureCompleted( + new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType, "Failed while executing " + testName); } } diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index f9b5c2a6c77f..43b065dbb6a5 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -70,7 +70,6 @@ import android.hardware.SensorPrivacyManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.input.InputManager; -import android.hardware.input.KeyboardSystemShortcut; import android.media.AudioManagerInternal; import android.os.Handler; import android.os.HandlerThread; @@ -804,11 +803,11 @@ class TestPhoneWindowManager { Assert.assertEquals(targetActivity, intentCaptor.getValue().getComponent()); } - void assertKeyboardShortcutTriggered(int[] keycodes, int modifierState, int systemShortcut, + void assertKeyGestureCompleted(int[] keycodes, int modifierState, int gestureType, String errorMsg) { mTestLooper.dispatchAll(); - verify(mInputManagerInternal, description(errorMsg)).notifyKeyboardShortcutTriggered( - anyInt(), eq(keycodes), eq(modifierState), eq(systemShortcut)); + verify(mInputManagerInternal, description(errorMsg)).notifyKeyGestureCompleted( + anyInt(), eq(keycodes), eq(modifierState), eq(gestureType)); } void assertSwitchToTask(int persistentId) throws RemoteException { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRefresherTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRefresherTests.java index 14fbbe4cf2ef..cb17f35f64d7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRefresherTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRefresherTests.java @@ -212,7 +212,6 @@ public class ActivityRefresherTests extends WindowTestsBase { .build() .getTopMostActivity(); - spyOn(mActivity.mLetterboxUiController); spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides()); doReturn(true).when(mActivity).inFreeformWindowingMode(); doReturn(true).when(mActivity.mAppCompatController diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java index a74572431d6b..fee9c6c002c4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java @@ -31,10 +31,10 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; -import android.app.WindowConfiguration; +import android.app.WindowConfiguration.WindowingMode; import android.content.ComponentName; import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; +import android.content.pm.PackageManager.UserMinAspectRatio; import android.content.res.Configuration; import android.graphics.Rect; import android.view.Surface; @@ -176,10 +176,14 @@ class AppCompatActivityRobot { return mActivityStack.getFromTop(fromTop); } - void setTaskWindowingMode(@WindowConfiguration.WindowingMode int windowingMode) { + void setTaskWindowingMode(@WindowingMode int windowingMode) { mTaskStack.top().setWindowingMode(windowingMode); } + void setTaskDisplayAreaWindowingMode(@WindowingMode int windowingMode) { + mTaskStack.top().getDisplayArea().setWindowingMode(windowingMode); + } + void setLetterboxedForFixedOrientationAndAspectRatio(boolean enabled) { doReturn(enabled).when(mActivityStack.top().mAppCompatController .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio(); @@ -222,10 +226,14 @@ class AppCompatActivityRobot { .getAppCompatAspectRatioOverrides()).shouldApplyUserFullscreenOverride(); } - void setGetUserMinAspectRatioOverrideCode(@PackageManager.UserMinAspectRatio int orientation) { - doReturn(orientation).when(mActivityStack.top() - .mAppCompatController.getAppCompatAspectRatioOverrides()) - .getUserMinAspectRatioOverrideCode(); + void setGetUserMinAspectRatioOverrideCode(@UserMinAspectRatio int overrideCode) { + doReturn(overrideCode).when(mActivityStack.top().mAppCompatController + .getAppCompatAspectRatioOverrides()).getUserMinAspectRatioOverrideCode(); + } + + void setGetUserMinAspectRatioOverrideValue(float overrideValue) { + doReturn(overrideValue).when(mActivityStack.top().mAppCompatController + .getAppCompatAspectRatioOverrides()).getUserMinAspectRatio(); } void setIgnoreOrientationRequest(boolean enabled) { @@ -233,8 +241,7 @@ class AppCompatActivityRobot { } void setTopTaskInMultiWindowMode(boolean inMultiWindowMode) { - doReturn(inMultiWindowMode).when(mTaskStack.top()) - .inMultiWindowMode(); + doReturn(inMultiWindowMode).when(mTaskStack.top()).inMultiWindowMode(); } void setTopActivityAsEmbedded(boolean embedded) { @@ -420,7 +427,6 @@ class AppCompatActivityRobot { */ @CallSuper void onPostActivityCreation(@NonNull ActivityRecord activity) { - spyOn(activity.mLetterboxUiController); if (mOnPostActivityCreation != null) { mOnPostActivityCreation.accept(activity); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java index 84ffcb8956a9..ba2a7335824c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java @@ -374,7 +374,6 @@ public class AppCompatCameraOverridesTest extends WindowTestsBase { * Runs a test scenario providing a Robot. */ void runTestScenario(@NonNull Consumer<CameraOverridesRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final CameraOverridesRobotTest robot = new CameraOverridesRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java index c42228dcc6ba..2ae23f88812a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java @@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import android.compat.testing.PlatformCompatChangeRule; @@ -29,7 +31,6 @@ import android.platform.test.annotations.Presubmit; import androidx.annotation.NonNull; -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; @@ -53,18 +54,28 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @Test public void testDisplayRotationCompatPolicy_presentWhenEnabled() { runTestScenario((robot) -> { - robot.conf().enableCameraCompatTreatmentAtBuildTime(true); + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasDisplayRotationCompatPolicy(true); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ true); }); } @Test public void testDisplayRotationCompatPolicy_notPresentWhenDisabled() { runTestScenario((robot) -> { - robot.conf().enableCameraCompatTreatmentAtBuildTime(false); + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ false); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasDisplayRotationCompatPolicy(false); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ false); + }); + } + + @Test + public void testDisplayRotationCompatPolicy_startedWhenEnabled() { + runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ true); + robot.checkTopActivityDisplayRotationCompatPolicyIsRunning(); }); } @@ -72,9 +83,9 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) public void testCameraCompatFreeformPolicy_presentWhenEnabledAndDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(true); + robot.allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasCameraCompatFreeformPolicy(true); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); }); } @@ -82,9 +93,9 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) public void testCameraCompatFreeformPolicy_notPresentWhenNoDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(false); + robot.allowEnterDesktopMode(/* isAllowed= */ false); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasCameraCompatFreeformPolicy(false); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); }); } @@ -92,9 +103,9 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @DisableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) public void testCameraCompatFreeformPolicy_notPresentWhenNoFlag() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(true); + robot.allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasCameraCompatFreeformPolicy(false); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); }); } @@ -102,19 +113,86 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) public void testCameraCompatFreeformPolicy_notPresentWhenNoFlagAndNoDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(false); + robot.allowEnterDesktopMode(/* isAllowed= */ false); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); + }); + } + + @Test + @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) + public void testCameraCompatFreeformPolicy_startedWhenEnabledAndDW() { + runTestScenario((robot) -> { + robot.allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); - robot.checkTopActivityHasCameraCompatFreeformPolicy(false); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); + robot.checkTopActivityCameraCompatFreeformPolicyIsRunning(); + }); + } + + @Test + @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) + public void testCameraStateManager_existsWhenCameraCompatFreeformExists() { + runTestScenario((robot) -> { + robot.allowEnterDesktopMode(true); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); + robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); + }); + } + + @Test + @EnableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) + public void testCameraStateManager_startedWhenCameraCompatFreeformExists() { + runTestScenario((robot) -> { + robot.allowEnterDesktopMode(true); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); + robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); + robot.checkTopActivityCameraStateMonitorIsRunning(); + }); + } + + @Test + public void testCameraStateManager_existsWhenDisplayRotationCompatPolicyExists() { + runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ true); + robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); + }); + } + + @Test + public void testCameraStateManager_startedWhenDisplayRotationCompatPolicyExists() { + runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ true); + robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); + robot.checkTopActivityCameraStateMonitorIsRunning(); + }); + } + + @Test + @DisableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM) + public void testCameraStateManager_doesNotExistWhenNoPolicyExists() { + runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ false); + robot.activity().createActivityWithComponentInNewTaskAndDisplay(); + robot.checkTopActivityHasDisplayRotationCompatPolicy(/* exists= */ false); + robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); + robot.checkTopActivityHasCameraStateMonitor(/* exists= */ false); }); } /** * Runs a test scenario providing a Robot. */ - void runTestScenario(@NonNull Consumer<DisplayRotationPolicyRobotTest> consumer) { + void runTestScenario(@NonNull Consumer<AppCompatCameraPolicyRobotTest> consumer) { spyOn(mWm.mAppCompatConfiguration); - final DisplayRotationPolicyRobotTest robot = - new DisplayRotationPolicyRobotTest(mWm, mAtm, mSupervisor); + final AppCompatCameraPolicyRobotTest robot = + new AppCompatCameraPolicyRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); } @@ -142,9 +220,8 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { }); } - private static class DisplayRotationPolicyRobotTest extends AppCompatRobotBase { - - DisplayRotationPolicyRobotTest(@NonNull WindowManagerService wm, + private static class AppCompatCameraPolicyRobotTest extends AppCompatRobotBase { + AppCompatCameraPolicyRobotTest(@NonNull WindowManagerService wm, @NonNull ActivityTaskManagerService atm, @NonNull ActivityTaskSupervisor supervisor) { super(wm, atm, supervisor); @@ -157,17 +234,37 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { } void checkTopActivityHasDisplayRotationCompatPolicy(boolean exists) { - Assert.assertEquals(exists, activity().top().mDisplayContent - .mAppCompatCameraPolicy.hasDisplayRotationCompatPolicy()); + assertEquals(exists, activity().top().mDisplayContent.mAppCompatCameraPolicy + .hasDisplayRotationCompatPolicy()); } void checkTopActivityHasCameraCompatFreeformPolicy(boolean exists) { - Assert.assertEquals(exists, activity().top().mDisplayContent - .mAppCompatCameraPolicy.hasCameraCompatFreeformPolicy()); + assertEquals(exists, activity().top().mDisplayContent.mAppCompatCameraPolicy + .hasCameraCompatFreeformPolicy()); + } + + void checkTopActivityHasCameraStateMonitor(boolean exists) { + assertEquals(exists, activity().top().mDisplayContent.mAppCompatCameraPolicy + .hasCameraStateMonitor()); + } + + void checkTopActivityDisplayRotationCompatPolicyIsRunning() { + assertTrue(activity().top().mDisplayContent.mAppCompatCameraPolicy + .mDisplayRotationCompatPolicy.isRunning()); + } + + void checkTopActivityCameraCompatFreeformPolicyIsRunning() { + assertTrue(activity().top().mDisplayContent.mAppCompatCameraPolicy + .mCameraCompatFreeformPolicy.isRunning()); + } + + void checkTopActivityCameraStateMonitorIsRunning() { + assertTrue(activity().top().mDisplayContent.mAppCompatCameraPolicy + .mCameraStateMonitor.isRunning()); } void checkIsCameraCompatTreatmentActiveForTopActivity(boolean active) { - Assert.assertEquals(getTopAppCompatCameraPolicy() + assertEquals(getTopAppCompatCameraPolicy() .isTreatmentEnabledForActivity(activity().top()), active); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java index 40a53479e9ab..776005101b70 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatConfigurationRobot.java @@ -52,6 +52,11 @@ class AppCompatConfigurationRobot { doReturn(enabled).when(mAppCompatConfiguration).isCameraCompatTreatmentEnabled(); } + void enableSplitScreenAspectRatioForUnresizableApps(boolean enabled) { + doReturn(enabled).when(mAppCompatConfiguration) + .getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); + } + void enableCameraCompatTreatmentAtBuildTime(boolean enabled) { doReturn(enabled).when(mAppCompatConfiguration) .isCameraCompatTreatmentEnabledAtBuildTime(); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatFocusOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatFocusOverridesTest.java index 27c5e4ebb397..d8f845389727 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatFocusOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatFocusOverridesTest.java @@ -19,8 +19,6 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; - import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.Presubmit; @@ -177,7 +175,6 @@ public class AppCompatFocusOverridesTest extends WindowTestsBase { * Runs a test scenario providing a Robot. */ void runTestScenario(@NonNull Consumer<FocusOverridesRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final FocusOverridesRobotTest robot = new FocusOverridesRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java index f6d0744a10c4..9057b6cb99ea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java @@ -514,7 +514,6 @@ public class AppCompatOrientationPolicyTest extends WindowTestsBase { */ void runTestScenario(boolean withActivity, @NonNull Consumer<OrientationPolicyRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final OrientationPolicyRobotTest robot = new OrientationPolicyRobotTest(mWm, mAtm, mSupervisor, withActivity); consumer.accept(robot); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java index 5ff8f0200fa3..1edbcd527bf4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java @@ -164,7 +164,6 @@ public class AppCompatReachabilityOverridesTest extends WindowTestsBase { * Runs a test scenario providing a Robot. */ void runTestScenario(@NonNull Consumer<ReachabilityOverridesRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final ReachabilityOverridesRobotTest robot = new ReachabilityOverridesRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java index 96734b389947..ddc4de9cfd8a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java @@ -228,7 +228,6 @@ public class AppCompatReachabilityPolicyTest extends WindowTestsBase { * Runs a test scenario providing a Robot. */ void runTestScenario(@NonNull Consumer<ReachabilityPolicyRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final ReachabilityPolicyRobotTest robot = new ReachabilityPolicyRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java index cade213ca3d7..b8d554b405d1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java @@ -20,8 +20,6 @@ import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP; import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; - import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.Presubmit; @@ -171,7 +169,6 @@ public class AppCompatResizeOverridesTest extends WindowTestsBase { * Runs a test scenario providing a Robot. */ void runTestScenario(@NonNull Consumer<ResizeOverridesRobotTest> consumer) { - spyOn(mWm.mAppCompatConfiguration); final ResizeOverridesRobotTest robot = new ResizeOverridesRobotTest(mWm, mAtm, mSupervisor); consumer.accept(robot); } diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java index f2592d2361f5..5a3ae769ef62 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java @@ -276,7 +276,6 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { .setTask(mTask) .build(); - spyOn(mActivity.mLetterboxUiController); spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides()); spyOn(mActivity.info); diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java index d2232729f271..ad80f82c8ea8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java @@ -189,7 +189,6 @@ public final class CameraStateMonitorTests extends WindowTestsBase { .build(); spyOn(mActivity.mAtmService.getLifecycleManager()); - spyOn(mActivity.mLetterboxUiController); doReturn(mActivity).when(mDisplayContent).topRunningActivity(anyBoolean()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopAppCompatAspectRatioPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopAppCompatAspectRatioPolicyTests.java new file mode 100644 index 000000000000..f4e1d4967ff5 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/DesktopAppCompatAspectRatioPolicyTests.java @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; + +import android.compat.testing.PlatformCompatChangeRule; +import android.content.pm.ActivityInfo; +import android.graphics.Rect; +import android.platform.test.annotations.Presubmit; + +import androidx.annotation.NonNull; + +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; + +import java.util.function.Consumer; + +/** + * Test class for {@link DesktopAppCompatAspectRatioPolicy}. + * <p> + * Build/Install/Run: + * atest WmTests:DesktopAppCompatAspectRatioPolicyTests + */ +@Presubmit +@RunWith(WindowTestRunner.class) +public class DesktopAppCompatAspectRatioPolicyTests extends WindowTestsBase { + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + + private static final float FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.33f; + + @Test + public void testHasMinAspectRatioOverride_userAspectRatioEnabled_returnTrue() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(3 / 2f); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_3_2); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ true); + }); + } + + @Test + @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) + public void testHasMinAspectRatioOverride_overrideDisabled_returnsFalse() { + runTestScenario((robot)-> { + robot.activity().createActivityWithComponent(); + + robot.checkHasMinAspectRatioOverride(/* expected */ false); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) + public void testHasMinAspectRatioOverride_overrideEnabled_propertyFalse_returnsFalse() { + runTestScenario((robot)-> { + robot.activity().createActivityWithComponent(); + robot.prop().disable(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE); + + robot.checkHasMinAspectRatioOverride(/* expected */ false); + }); + } + + @Test + @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) + public void testHasMinAspectRatioOverride_overrideDisabled_propertyTrue_returnsFalse() { + runTestScenario((robot)-> { + robot.activity().createActivityWithComponent(); + robot.prop().enable(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE); + + robot.checkHasMinAspectRatioOverride(/* expected */ false); + }); + } + + @Test + @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) + public void testHasMinAspectRatioOverride_overrideEnabled_nonPortraitActivity_returnsFalse() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_UNSPECIFIED); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ false); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN}) + public void testHasMinAspectRatioOverride_splitScreenAspectRatioOverride_returnTrue() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ true); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) + public void testHasMinAspectRatioOverride_largeMinAspectRatioOverride_returnTrue() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ true); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) + public void testHasMinAspectRatioOverride_mediumMinAspectRatioOverride_returnTrue() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ true); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL}) + public void testHasMinAspectRatioOverride_smallMinAspectRatioOverride_returnTrue() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + + robot.checkHasMinAspectRatioOverride(/* expected */ true); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN}) + public void testCalculateAspectRatio_splitScreenAspectRatioOverride() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ false); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioSplitScreenAspectRatio(); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) + public void testCalculateAspectRatio_largeMinAspectRatioOverride() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ false); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioLargeAspectRatioOverride(); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) + public void testCalculateAspectRatio_mediumMinAspectRatioOverride() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ false); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioMediumAspectRatioOverride(); + }); + } + + @Test + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL}) + public void testCalculateAspectRatio_smallMinAspectRatioOverride() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ false); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioSmallAspectRatioOverride(); + }); + } + + @Test + public void testCalculateAspectRatio_defaultMultiWindowLetterboxAspectRatio() { + runTestScenario((robot)-> { + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ false); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + a.setTaskDisplayAreaWindowingMode(WINDOWING_MODE_FREEFORM); + }); + + robot.checkCalculateAspectRatioDefaultLetterboxAspectRatioForMultiWindow(); + }); + } + + @Test + public void testCalculateAspectRatio_displayAspectRatioEnabledForFixedOrientationLetterbox() { + runTestScenario((robot)-> { + robot.conf().enableDisplayAspectRatioEnabledForFixedOrientationLetterbox(true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.configureTopActivity(/* minAspect */ 0, /* maxAspect */ 0, + SCREEN_ORIENTATION_PORTRAIT, /* isUnresizable */ false); + }); + + robot.checkCalculateAspectRatioDisplayAreaAspectRatio(); + }); + } + + @Test + public void testCalculateAspectRatio_defaultMinAspectRatio_fixedOrientationAspectRatio() { + runTestScenario((robot)-> { + robot.applyOnConf((c) -> { + c.enableDisplayAspectRatioEnabledForFixedOrientationLetterbox(false); + c.setFixedOrientationLetterboxAspectRatio(FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO); + }); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.configureTopActivity(/* minAspect */ 0, /* maxAspect */ 0, + SCREEN_ORIENTATION_PORTRAIT, /* isUnresizable */ false); + }); + + robot.checkCalculateAspectRatioDefaultMinFixedOrientationAspectRatio(); + }); + } + + @Test + public void testCalculateAspectRatio_splitScreenForUnresizeableEnabled() { + runTestScenario((robot) -> { + robot.conf().enableSplitScreenAspectRatioForUnresizableApps(/* isEnabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_PORTRAIT); + }); + + robot.checkCalculateAspectRatioSplitScreenAspectRatio(); + }); + } + + @Test + public void testCalculateAspectRatio_user3By2AspectRatioOverride() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(3 / 2f); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_3_2); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioUser3By2AspectRatiOverride(); + }); + } + + @Test + public void testCalculateAspectRatio_user4By3AspectRatioOverride() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(4 / 3f); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_4_3); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioUser4By3AspectRatiOverride(); + }); + } + + @Test + public void testCalculateAspectRatio_user16By9AspectRatioOverride() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(16 / 9f); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_16_9); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioUser16By9AspectRatioOverride(); + }); + } + + @Test + public void testCalculateAspectRatio_userSplitScreenAspectRatioOverride() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(robot.getSplitScreenAspectRatio()); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioSplitScreenAspectRatio(); + }); + } + + @Test + public void testCalculateAspectRatio_userDisplayAreaAspectRatioOverride() { + runTestScenario((robot)-> { + robot.conf().enableUserAppAspectRatioSettings(/* enabled */ true); + robot.applyOnActivity((a) -> { + a.createActivityWithComponent(); + a.setIgnoreOrientationRequest(/* enabled */ true); + a.setGetUserMinAspectRatioOverrideValue(robot.getDisplayAreaAspectRatio()); + a.setGetUserMinAspectRatioOverrideCode(USER_MIN_ASPECT_RATIO_DISPLAY_SIZE); + }); + robot.setDesiredAspectRatio(1f); + + robot.checkCalculateAspectRatioDisplayAreaAspectRatio(); + }); + } + + /** + * Runs a test scenario providing a Robot. + */ + void runTestScenario(@NonNull Consumer<DesktopAppCompatAspectRatioPolicyRobotTest> consumer) { + final DesktopAppCompatAspectRatioPolicyRobotTest robot = + new DesktopAppCompatAspectRatioPolicyRobotTest(mWm, mAtm, mSupervisor); + consumer.accept(robot); + } + + private static class DesktopAppCompatAspectRatioPolicyRobotTest extends AppCompatRobotBase { + DesktopAppCompatAspectRatioPolicyRobotTest(@NonNull WindowManagerService wm, + @NonNull ActivityTaskManagerService atm, + @NonNull ActivityTaskSupervisor supervisor) { + super(wm, atm, supervisor); + } + + @Override + void onPostActivityCreation(@NonNull ActivityRecord activity) { + super.onPostActivityCreation(activity); + spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides()); + spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy()); + } + + void setDesiredAspectRatio(float aspectRatio) { + doReturn(aspectRatio).when(getDesktopAppCompatAspectRatioPolicy()) + .getDesiredAspectRatio(any()); + } + + DesktopAppCompatAspectRatioPolicy getDesktopAppCompatAspectRatioPolicy() { + return getTopActivity().mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + } + + float calculateAspectRatio() { + return getDesktopAppCompatAspectRatioPolicy().calculateAspectRatio( + getTopActivity().getTask()); + } + + ActivityRecord getTopActivity() { + return this.activity().top(); + } + + float getSplitScreenAspectRatio() { + return getTopActivity().mAppCompatController.getAppCompatAspectRatioOverrides() + .getSplitScreenAspectRatio(); + } + + float getDisplayAreaAspectRatio() { + final Rect appBounds = getTopActivity().getDisplayArea().getWindowConfiguration() + .getAppBounds(); + return AppCompatUtils.computeAspectRatio(appBounds); + } + + void checkHasMinAspectRatioOverride(boolean expected) { + assertEquals(expected, this.activity().top().mAppCompatController + .getDesktopAppCompatAspectRatioPolicy().hasMinAspectRatioOverride( + this.activity().top().getTask())); + } + + void checkCalculateAspectRatioSplitScreenAspectRatio() { + assertEquals(getSplitScreenAspectRatio(), calculateAspectRatio(), FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioLargeAspectRatioOverride() { + assertEquals(OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE, calculateAspectRatio(), + FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioMediumAspectRatioOverride() { + assertEquals(OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE, calculateAspectRatio(), + FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioSmallAspectRatioOverride() { + assertEquals(OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE, calculateAspectRatio(), + FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioDefaultLetterboxAspectRatioForMultiWindow() { + assertEquals(DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW, calculateAspectRatio(), + FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioDisplayAreaAspectRatio() { + assertEquals(getDisplayAreaAspectRatio(), calculateAspectRatio(), FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioDefaultMinFixedOrientationAspectRatio() { + assertEquals(FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO, calculateAspectRatio(), + FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioUser3By2AspectRatiOverride() { + assertEquals(3 / 2f, calculateAspectRatio(), FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioUser4By3AspectRatiOverride() { + assertEquals(4 / 3f, calculateAspectRatio(), FLOAT_TOLLERANCE); + } + + void checkCalculateAspectRatioUser16By9AspectRatioOverride() { + assertEquals(16 / 9f, calculateAspectRatio(), FLOAT_TOLLERANCE); + } + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java index 07e95d83d7bc..6d508eabcd52 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java @@ -21,11 +21,19 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE; +import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE; +import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.util.DisplayMetrics.DENSITY_DEFAULT; @@ -34,7 +42,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_INITIAL_BOUNDS_SCALE; import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_LANDSCAPE_APP_PADDING; -import static com.android.server.wm.DesktopModeBoundsCalculator.calculateAspectRatio; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP; @@ -44,6 +51,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import android.app.ActivityOptions; +import android.compat.testing.PlatformCompatChangeRule; +import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.platform.test.annotations.DisableFlags; @@ -55,8 +64,12 @@ import androidx.test.filters.SmallTest; import com.android.window.flags.Flags; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; /** @@ -74,6 +87,9 @@ public class DesktopModeLaunchParamsModifierTests extends private static final Rect PORTRAIT_DISPLAY_BOUNDS = new Rect(0, 0, 1600, 2560); private static final float LETTERBOX_ASPECT_RATIO = 1.3f; + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + @Before public void setUp() throws Exception { mActivity = new ActivityBuilder(mAtm).build(); @@ -199,14 +215,17 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); final int desiredWidth = (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -219,14 +238,17 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); final int desiredWidth = (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -239,7 +261,9 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()); doReturn(true).when( @@ -251,7 +275,8 @@ public class DesktopModeLaunchParamsModifierTests extends final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -264,7 +289,9 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()); doReturn(true).when( @@ -276,7 +303,8 @@ public class DesktopModeLaunchParamsModifierTests extends final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -285,19 +313,466 @@ public class DesktopModeLaunchParamsModifierTests extends @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) public void testResizablePortraitBounds_landscapeDevice_resizable_portraitOrientation() { setupDesktopModeLaunchParamsModifier(); - doReturn(LETTERBOX_ASPECT_RATIO).when(() - -> calculateAspectRatio(any(), any())); final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); + + spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy()); + doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController + .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any()); final int desiredWidth = (int) ((LANDSCAPE_DISPLAY_BOUNDS.height() / LETTERBOX_ASPECT_RATIO) + 0.5f); final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL}) + public void testSmallAspectRatioOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = + (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) + public void testMediumAspectRatioOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = + (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) + public void testLargeAspectRatioOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = + (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN}) + public void testSplitScreenAspectRatioOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = + (int) (desiredHeight / activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio()); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL}) + public void testSmallAspectRatioOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + // Mock desired aspect ratio so min override can take effect. + setDesiredAspectRatio(activity, /* aspectRatio */ 1f); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) + public void testMediumAspectRatioOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + // Mock desired aspect ratio so min override can take effect. + setDesiredAspectRatio(activity, /* aspectRatio */ 1f); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) + public void testLargeAspectRatioOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + // Mock desired aspect ratio so min override can take effect. + setDesiredAspectRatio(activity, /* aspectRatio */ 1f); + + final int desiredHeight = + (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, + ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN}) + public void testSplitScreenAspectRatioOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ false); + // Mock desired aspect ratio so min override can take effect. + setDesiredAspectRatio(activity, /* aspectRatio */ 1f); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio()); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio32Override_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue3_2 = 3 / 2f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_3_2, + userAspectRatioOverrideValue3_2); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue3_2); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio43Override_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue4_3 = 4 / 3f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_4_3, + userAspectRatioOverrideValue4_3); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue4_3); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio169Override_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue16_9 = 16 / 9f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_16_9, + userAspectRatioOverrideValue16_9); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue16_9); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatioSplitScreenOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValueSplitScreen = activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio(); + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN, + userAspectRatioOverrideValueSplitScreen); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValueSplitScreen); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatioDisplaySizeOverride_landscapeDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValueDisplaySize = activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getDisplaySizeMinAspectRatio(); + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE, + userAspectRatioOverrideValueDisplaySize); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValueDisplaySize); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio32Override_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue3_2 = 3 / 2f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_3_2, + userAspectRatioOverrideValue3_2); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValue3_2); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio43Override_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue4_3 = 4 / 3f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_4_3, + userAspectRatioOverrideValue4_3); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValue4_3); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatio169Override_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValue16_9 = 16 / 9f; + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_16_9, + userAspectRatioOverrideValue16_9); + + final int desiredHeight = + (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue16_9); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatioSplitScreenOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValueSplitScreen = activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio(); + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN, + userAspectRatioOverrideValueSplitScreen); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValueSplitScreen); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUserAspectRatioDisplaySizeOverride_portraitDevice() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); + final float userAspectRatioOverrideValueDisplaySize = activity.mAppCompatController + .getAppCompatAspectRatioOverrides().getDisplaySizeMinAspectRatio(); + applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE, + userAspectRatioOverrideValueDisplaySize); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValueDisplaySize); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -310,14 +785,18 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false); + final Task task = createTask(display, /* isResizeable */ false); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); + final int desiredWidth = (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -326,18 +805,23 @@ public class DesktopModeLaunchParamsModifierTests extends @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) public void testUnResizablePortraitBounds_landscapeDevice_unResizable_portraitOrientation() { setupDesktopModeLaunchParamsModifier(); - doReturn(LETTERBOX_ASPECT_RATIO).when(() - -> calculateAspectRatio(any(), any())); final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, LANDSCAPE_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false); + final Task task = createTask(display, /* isResizeable */ false); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); + + spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy()); + doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController + .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any()); final int desiredHeight = (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredWidth = (int) (desiredHeight / LETTERBOX_ASPECT_RATIO); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -350,14 +834,17 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED, + task, /* ignoreOrientationRequest */ true); final int desiredWidth = (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -370,14 +857,17 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); final int desiredWidth = (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -390,11 +880,13 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); - spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()); + spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides()); doReturn(true).when( - mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()) + activity.mAppCompatController.getAppCompatAspectRatioOverrides()) .isUserFullscreenOverrideEnabled(); final int desiredWidth = @@ -402,7 +894,8 @@ public class DesktopModeLaunchParamsModifierTests extends final int desiredHeight = (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -415,11 +908,13 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); - spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()); + spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides()); doReturn(true).when( - mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()) + activity.mAppCompatController.getAppCompatAspectRatioOverrides()) .isSystemOverrideToFullscreenEnabled(); final int desiredWidth = @@ -427,7 +922,8 @@ public class DesktopModeLaunchParamsModifierTests extends final int desiredHeight = (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -436,19 +932,24 @@ public class DesktopModeLaunchParamsModifierTests extends @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) public void testResizableLandscapeBounds_portraitDevice_resizable_landscapeOrientation() { setupDesktopModeLaunchParamsModifier(); - doReturn(LETTERBOX_ASPECT_RATIO).when(() - -> calculateAspectRatio(any(), any())); final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + final Task task = createTask(display, /* isResizeable */ true); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); + + spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy()); + doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController + .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any()); final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); final int desiredHeight = (int) ((PORTRAIT_DISPLAY_BOUNDS.width() / LETTERBOX_ASPECT_RATIO) + 0.5f); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -461,14 +962,18 @@ public class DesktopModeLaunchParamsModifierTests extends final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false); + final Task task = createTask(display, /* isResizeable */ false); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT, + task, /* ignoreOrientationRequest */ true); + final int desiredWidth = (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -477,18 +982,23 @@ public class DesktopModeLaunchParamsModifierTests extends @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) public void testUnResizableLandscapeBounds_portraitDevice_unResizable_landscapeOrientation() { setupDesktopModeLaunchParamsModifier(); - doReturn(LETTERBOX_ASPECT_RATIO).when(() - -> calculateAspectRatio(any(), any())); final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, PORTRAIT_DISPLAY_BOUNDS); - final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false); + final Task task = createTask(display, /* isResizeable */ false); + final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE, + task, /* ignoreOrientationRequest */ true); + + spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy()); + doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController + .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any()); final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); final int desiredHeight = (int) (desiredWidth / LETTERBOX_ASPECT_RATIO); - assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task) + .setActivity(activity).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); } @@ -755,24 +1265,64 @@ public class DesktopModeLaunchParamsModifierTests extends assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode); } - private Task createTask(DisplayContent display, int orientation, Boolean isResizeable) { + private Task createTask(DisplayContent display, Boolean isResizeable) { final int resizeMode = isResizeable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE; final Task task = new TaskBuilder(mSupervisor).setActivityType( ACTIVITY_TYPE_STANDARD).setDisplay(display).build(); task.setResizeMode(resizeMode); - mActivity = new ActivityBuilder(task.mAtmService) + return task; + } + + private ActivityRecord createActivity(DisplayContent display, int orientation, Task task, + boolean ignoreOrientationRequest) { + final ActivityRecord activity = new ActivityBuilder(task.mAtmService) .setTask(task) + .setComponent(ComponentName.createRelative(task.mAtmService.mContext, + DesktopModeLaunchParamsModifierTests.class.getName())) + .setUid(android.os.Process.myUid()) .setScreenOrientation(orientation) .setOnTop(true).build(); + activity.onDisplayChanged(display); + activity.setOccludesParent(true); + activity.setVisible(true); + activity.setVisibleRequested(true); + activity.mDisplayContent.setIgnoreOrientationRequest(ignoreOrientationRequest); - mActivity.onDisplayChanged(display); - mActivity.setOccludesParent(true); - mActivity.setVisible(true); - mActivity.setVisibleRequested(true); - mActivity.mDisplayContent.setIgnoreOrientationRequest(/* ignoreOrientationRequest */ true); + return activity; + } - return task; + private void setDesiredAspectRatio(ActivityRecord activity, float aspectRatio) { + final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy = + activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + spyOn(desktopAppCompatAspectRatioPolicy); + doReturn(aspectRatio).when(desktopAppCompatAspectRatioPolicy) + .getDesiredAspectRatio(any()); + } + + private void applyUserMinAspectRatioOverride(ActivityRecord activity, int overrideCode, + float overrideValue) { + // Set desired aspect ratio to be below minimum so override can take effect. + final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy = + activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + spyOn(desktopAppCompatAspectRatioPolicy); + doReturn(1f).when(desktopAppCompatAspectRatioPolicy) + .getDesiredAspectRatio(any()); + + // Enable user aspect ratio settings + final AppCompatConfiguration appCompatConfiguration = + activity.mWmService.mAppCompatConfiguration; + spyOn(appCompatConfiguration); + doReturn(true).when(appCompatConfiguration) + .isUserAppAspectRatioSettingsEnabled(); + + // Simulate user min aspect ratio override being set. + final AppCompatAspectRatioOverrides appCompatAspectRatioOverrides = + activity.mAppCompatController.getAppCompatAspectRatioOverrides(); + spyOn(appCompatAspectRatioOverrides); + doReturn(overrideValue).when(appCompatAspectRatioOverrides).getUserMinAspectRatio(); + doReturn(overrideCode).when(appCompatAspectRatioOverrides) + .getUserMinAspectRatioOverrideCode(); } private TestDisplayContent createDisplayContent(int orientation, Rect displayBounds) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index ab0c8d4ed60a..ec5e51e7b842 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -2656,6 +2656,7 @@ public class DisplayContentTests extends WindowTestsBase { * display. */ @Test + @SuppressWarnings("GuardedBy") public void testNotResumeHomeRootTaskOnRemovingDisplay() { // Create a display which supports system decoration and allows reparenting root tasks to // another display when the display is removed. @@ -2678,7 +2679,8 @@ public class DisplayContentTests extends WindowTestsBase { // The removed display should have no focused root task and its home root task should never // resume. assertNull(display.getFocusedRootTask()); - verify(homeRootTask, never()).resumeTopActivityUncheckedLocked(any(), any()); + verify(homeRootTask, never()).resumeTopActivityUncheckedLocked( + any(), any(), anyBoolean()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java index 2dea6ba2b8aa..8cf593fd21db 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java @@ -597,7 +597,6 @@ public final class DisplayRotationCompatPolicyTests extends WindowTestsBase { .build(); spyOn(mActivity.mAtmService.getLifecycleManager()); - spyOn(mActivity.mLetterboxUiController); spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides()); doReturn(mActivity).when(mDisplayContent).topRunningActivity(anyBoolean()); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index ddadbc41a1c0..57839e2b795e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -309,6 +309,16 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { public void testPublicDisplayDefaultToMoveToPrimary() { assertEquals(REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY, mDisplayWindowSettings.getRemoveContentModeLocked(mSecondaryDisplay)); + + // Sets the remove-content-mode and make sure the mode is updated. + mDisplayWindowSettings.setRemoveContentModeLocked(mSecondaryDisplay, + REMOVE_CONTENT_MODE_DESTROY); + final int removeContentMode = mDisplayWindowSettings.getRemoveContentModeLocked( + mSecondaryDisplay); + assertEquals(REMOVE_CONTENT_MODE_DESTROY, removeContentMode); + + doReturn(removeContentMode).when(mSecondaryDisplay).getRemoveContentMode(); + assertTrue(mSecondaryDisplay.shouldDestroyContentOnRemove()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index cf321ed89c89..894752218fcd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -77,7 +77,6 @@ public class LetterboxUiControllerTest extends WindowTestsBase { private ActivityRecord mActivity; private Task mTask; private DisplayContent mDisplayContent; - private LetterboxUiController mController; private AppCompatConfiguration mAppCompatConfiguration; private final Rect mLetterboxedPortraitTaskBounds = new Rect(); @@ -87,8 +86,6 @@ public class LetterboxUiControllerTest extends WindowTestsBase { mAppCompatConfiguration = mWm.mAppCompatConfiguration; spyOn(mAppCompatConfiguration); - - mController = new LetterboxUiController(mWm, mActivity); } @Test @@ -276,10 +273,13 @@ public class LetterboxUiControllerTest extends WindowTestsBase { final Resources resources = mWm.mContext.getResources(); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(); + final AppCompatAspectRatioPolicy aspectRatioPolicy = mActivity.mAppCompatController + .getAppCompatAspectRatioPolicy(); + mainWindow.mInvGlobalScale = 1f; spyOn(resources); spyOn(mActivity); - spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()); + spyOn(aspectRatioPolicy); if (taskbar != null) { taskbar.setVisible(true); @@ -288,8 +288,8 @@ public class LetterboxUiControllerTest extends WindowTestsBase { doReturn(mLetterboxedPortraitTaskBounds).when(mActivity).getBounds(); doReturn(false).when(mActivity).isInLetterboxAnimation(); doReturn(true).when(mActivity).isVisible(); - doReturn(true).when(mActivity.mAppCompatController - .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio(); + doReturn(true).when(aspectRatioPolicy) + .isLetterboxedForFixedOrientationAndAspectRatio(); doReturn(insets).when(mainWindow).getInsetsState(); doReturn(attrs).when(mainWindow).getAttrs(); doReturn(true).when(mainWindow).isDrawn(); @@ -300,9 +300,6 @@ public class LetterboxUiControllerTest extends WindowTestsBase { doReturn(TASKBAR_EXPANDED_HEIGHT).when(resources).getDimensionPixelSize( R.dimen.taskbar_frame_height); - // Need to reinitialise due to the change in resources getDimensionPixelSize output. - mController = new LetterboxUiController(mWm, mActivity); - return mainWindow; } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index d29505f02fe8..4ab2fcf095d1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -54,6 +54,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.refEq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; @@ -204,6 +205,28 @@ public class RootWindowContainerTests extends WindowTestsBase { } @Test + public void testAllResumedActivitiesIdle() { + final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build(); + final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build(); + final WindowProcessController proc2 = activity2.app; + activity1.setState(RESUMED, "test"); + activity2.detachFromProcess(); + assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse(); + + activity1.idle = true; + assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse(); + + activity2.setProcess(proc2); + activity2.setState(RESUMED, "test"); + activity2.idle = true; + assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue(); + + activity1.idle = false; + activity1.setVisibleRequested(false); + assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue(); + } + + @Test public void testTaskLayerRank() { final Task rootTask = new TaskBuilder(mSupervisor).build(); final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build(); @@ -598,7 +621,7 @@ public class RootWindowContainerTests extends WindowTestsBase { mRootWindowContainer.applySleepTokens(true); verify(task, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleeping(); verify(task, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked( - null /* target */, null /* targetOptions */); + isNull() /* target */, isNull() /* targetOptions */, eq(false) /* deferPause */); } @Test @@ -790,8 +813,7 @@ public class RootWindowContainerTests extends WindowTestsBase { doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask(); // Use the task as target to resume. - mRootWindowContainer.resumeFocusedTasksTopActivities(rootTask, activity, - null /* targetOptions */); + mRootWindowContainer.resumeFocusedTasksTopActivities(rootTask, activity); // Verify the target task should resume its activity. verify(rootTask, times(1)).resumeTopActivityUncheckedLocked( diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 36696a16fa39..1e1055bb233a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -2394,7 +2394,13 @@ public class SizeCompatTests extends WindowTestsBase { private void testUserOverrideAspectRatio(boolean isUnresizable, int screenOrientation, float expectedAspectRatio, @PackageManager.UserMinAspectRatio int aspectRatio, boolean enabled) { - final ActivityRecord activity = getActivityBuilderOnSameTask().build(); + final ActivityRecord activity = getActivityBuilderWithoutTask().build(); + final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy = + activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy(); + spyOn(desktopAppCompatAspectRatioPolicy); + doReturn(enabled).when(desktopAppCompatAspectRatioPolicy) + .hasMinAspectRatioOverride(any()); + mTask.addChild(activity); activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); spyOn(activity.mWmService.mAppCompatConfiguration); doReturn(enabled).when(activity.mWmService.mAppCompatConfiguration) @@ -3017,6 +3023,7 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + @SuppressWarnings("GuardedBy") public void testDisplayIgnoreOrientationRequest_pausedAppNotLostSizeCompat() { // Set up a display in landscape and ignoring orientation request. setUpDisplaySizeWithApp(2800, 1400); @@ -3043,7 +3050,8 @@ public class SizeCompatTests extends WindowTestsBase { assertActivityMaxBoundsSandboxed(); final Rect activityBounds = new Rect(mActivity.getBounds()); - mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */); + mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */, + false /* deferPause */); // App still in size compat, and the bounds don't change. verify(mActivity, never()).clearSizeCompatMode(); @@ -4942,8 +4950,11 @@ public class SizeCompatTests extends WindowTestsBase { } private ActivityBuilder getActivityBuilderOnSameTask() { + return getActivityBuilderWithoutTask().setTask(mTask); + } + + private ActivityBuilder getActivityBuilderWithoutTask() { return new ActivityBuilder(mAtm) - .setTask(mTask) .setComponent(ComponentName.createRelative(mContext, SizeCompatTests.class.getName())) .setUid(android.os.Process.myUid()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 49e349caa379..56fca31afa37 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -1550,10 +1550,6 @@ public class TransitionTests extends WindowTestsBase { // An active transient launch overrides idle state to avoid clearing power mode before the // transition is finished. - spyOn(mRootWindowContainer.mTransitionController); - doAnswer(invocation -> controller.isTransientLaunch(invocation.getArgument(0))).when( - mRootWindowContainer.mTransitionController).isTransientLaunch(any()); - activity2.getTask().setResumedActivity(activity2, "test"); activity2.idle = true; assertFalse(mRootWindowContainer.allResumedActivitiesIdle()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 18255b8d82f8..f56825faab73 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -265,7 +265,7 @@ public class WindowOrganizerTests extends WindowTestsBase { rootTask.setTaskOrganizer(null); mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); - verify(mWm.mAtmService).removeTask(eq(rootTask.mTaskId)); + verify(mWm.mAtmService).removeTask(eq(rootTask)); } @Test @@ -283,7 +283,7 @@ public class WindowOrganizerTests extends WindowTestsBase { rootTask.setTaskOrganizer(null); mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); - verify(mWm.mAtmService, never()).removeTask(eq(rootTask.mTaskId)); + verify(mWm.mAtmService, never()).removeTask(eq(rootTask)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingLegacyTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingLegacyTest.java index 48a8d5502c64..a1d35a7d447c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingLegacyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingLegacyTest.java @@ -125,7 +125,7 @@ public class WindowTracingLegacyTest { public void trace_dumpsWindowManagerState_whenTracing() throws Exception { mWindowTracing.startTrace(mock(PrintWriter.class)); mWindowTracing.logState("where"); - verify(mWmMock, times(2)).dumpDebugLocked(any(), eq(WindowTraceLogLevel.TRIM)); + verify(mWmMock, times(2)).dumpDebugLocked(any(), eq(WindowTracingLogLevel.TRIM)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingPerfettoTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingPerfettoTest.java new file mode 100644 index 000000000000..1d567b1169bd --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingPerfettoTest.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2017 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.server.wm; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; + +import static java.io.File.createTempFile; +import static java.nio.file.Files.createTempDirectory; + +import android.platform.test.annotations.Presubmit; +import android.tools.ScenarioBuilder; +import android.tools.traces.io.ResultWriter; +import android.tools.traces.monitors.PerfettoTraceMonitor; +import android.view.Choreographer; + +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import perfetto.protos.PerfettoConfig.WindowManagerConfig.LogFrequency; + +/** + * Test class for {@link WindowTracingPerfetto}. + */ +@SmallTest +@Presubmit +public class WindowTracingPerfettoTest { + @Mock + private WindowManagerService mWmMock; + @Mock + private Choreographer mChoreographer; + private WindowTracing mWindowTracing; + private PerfettoTraceMonitor mTraceMonitor; + private ResultWriter mWriter; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mWindowTracing = new WindowTracingPerfetto(mWmMock, mChoreographer, + new WindowManagerGlobalLock()); + + mWriter = new ResultWriter() + .forScenario(new ScenarioBuilder() + .forClass(createTempFile("temp", "").getName()).build()) + .withOutputDir(createTempDirectory("temp").toFile()) + .setRunComplete(); + } + + @After + public void tearDown() throws Exception { + stopTracing(); + } + + @Test + public void isEnabled_returnsFalseByDefault() { + assertFalse(mWindowTracing.isEnabled()); + } + + @Test + public void isEnabled_returnsTrueAfterStartThenFalseAfterStop() { + startTracing(false); + assertTrue(mWindowTracing.isEnabled()); + + stopTracing(); + assertFalse(mWindowTracing.isEnabled()); + } + + @Test + public void trace_ignoresLogStateCalls_ifTracingIsDisabled() { + mWindowTracing.logState("where"); + verifyZeroInteractions(mWmMock); + } + + @Test + public void trace_writesInitialStateSnapshot_whenTracingStarts() throws Exception { + startTracing(false); + verify(mWmMock, times(1)).dumpDebugLocked(any(), eq(WindowTracingLogLevel.ALL)); + } + + @Test + public void trace_writesStateSnapshot_onLogStateCall() throws Exception { + startTracing(false); + mWindowTracing.logState("where"); + verify(mWmMock, times(2)).dumpDebugLocked(any(), eq(WindowTracingLogLevel.ALL)); + } + + @Test + public void dump_writesOneSingleStateSnapshot() throws Exception { + startTracing(true); + mWindowTracing.logState("where"); + verify(mWmMock, times(1)).dumpDebugLocked(any(), eq(WindowTracingLogLevel.ALL)); + } + + private void startTracing(boolean isDump) { + if (isDump) { + mTraceMonitor = PerfettoTraceMonitor + .newBuilder() + .enableWindowManagerDump() + .build(); + } else { + mTraceMonitor = PerfettoTraceMonitor + .newBuilder() + .enableWindowManagerTrace(LogFrequency.LOG_FREQUENCY_TRANSACTION) + .build(); + } + mTraceMonitor.start(); + } + + private void stopTracing() { + if (mTraceMonitor == null || !mTraceMonitor.isEnabled()) { + return; + } + mTraceMonitor.stop(mWriter); + } +} diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java index 65e8e13036a6..ddf5ef21face 100644 --- a/telephony/java/android/telephony/CarrierRestrictionRules.java +++ b/telephony/java/android/telephony/CarrierRestrictionRules.java @@ -463,8 +463,9 @@ public final class CarrierRestrictionRules implements Parcelable { public String toString() { return "CarrierRestrictionRules(allowed:" + mAllowedCarriers + ", excluded:" + mExcludedCarriers + ", default:" + mCarrierRestrictionDefault - + ", MultiSim policy:" + mMultiSimPolicy + getCarrierInfoList() + - " mIsCarrierLockInfoSupported = " + mUseCarrierLockInfo + ")"; + + ", MultiSim policy:" + mMultiSimPolicy + getCarrierInfoList() + + ", mIsCarrierLockInfoSupported = " + mUseCarrierLockInfo + + getCarrierRestrictionStatusToLog() + ")"; } private String getCarrierInfoList() { @@ -476,6 +477,13 @@ public final class CarrierRestrictionRules implements Parcelable { } } + private String getCarrierRestrictionStatusToLog() { + if(android.os.Build.isDebuggable()) { + return ", CarrierRestrictionStatus = " + mCarrierRestrictionStatus; + } + return ""; + } + /** * Builder for a {@link CarrierRestrictionRules}. */ diff --git a/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl index f981fb1d67c7..5f0d986912a1 100644 --- a/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl +++ b/telephony/java/android/telephony/satellite/ISatelliteProvisionStateCallback.aidl @@ -16,6 +16,8 @@ package android.telephony.satellite; +import android.telephony.satellite.SatelliteSubscriberProvisionStatus; + /** * Interface for satellite provision state callback. * @hide @@ -27,4 +29,14 @@ oneway interface ISatelliteProvisionStateCallback { * @param provisioned True means the service is provisioned and false means it is not. */ void onSatelliteProvisionStateChanged(in boolean provisioned); + + /** + * Called when the provisioning state of one or more SatelliteSubscriberInfos changes. + * + * @param satelliteSubscriberProvisionStatus The List contains the latest provisioning states of + * the SatelliteSubscriberInfos. + * @hide + */ + void onSatelliteSubscriptionProvisionStateChanged(in List<SatelliteSubscriberProvisionStatus> + satelliteSubscriberProvisionStatus); } diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index e657d7faad15..6ef953c505cb 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -234,7 +234,7 @@ public final class SatelliteManager { /** * Bundle key to get the response from - * {@link #requestProvisionSubscriberIds(Executor, OutcomeReceiver)}. + * {@link #requestSatelliteSubscriberProvisionStatus(Executor, OutcomeReceiver)}. * @hide */ public static final String KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN = @@ -242,13 +242,6 @@ public final class SatelliteManager { /** * Bundle key to get the response from - * {@link #requestIsProvisioned(String, Executor, OutcomeReceiver)}. - * @hide - */ - public static final String KEY_IS_SATELLITE_PROVISIONED = "request_is_satellite_provisioned"; - - /** - * Bundle key to get the response from * {@link #provisionSatellite(List, Executor, OutcomeReceiver)}. * @hide */ @@ -1404,6 +1397,16 @@ public final class SatelliteManager { () -> callback.onSatelliteProvisionStateChanged( provisioned))); } + + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + @Override + public void onSatelliteSubscriptionProvisionStateChanged( + @NonNull List<SatelliteSubscriberProvisionStatus> + satelliteSubscriberProvisionStatus) { + executor.execute(() -> Binder.withCleanCallingIdentity(() -> + callback.onSatelliteSubscriptionProvisionStateChanged( + satelliteSubscriberProvisionStatus))); + } }; sSatelliteProvisionStateCallbackMap.put(callback, internalCallback); return telephony.registerForSatelliteProvisionStateChanged( @@ -2641,8 +2644,10 @@ public final class SatelliteManager { */ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) - public void requestProvisionSubscriberIds(@NonNull @CallbackExecutor Executor executor, - @NonNull OutcomeReceiver<List<SatelliteSubscriberInfo>, SatelliteException> callback) { + public void requestSatelliteSubscriberProvisionStatus( + @NonNull @CallbackExecutor Executor executor, + @NonNull OutcomeReceiver<List<SatelliteSubscriberProvisionStatus>, + SatelliteException> callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); @@ -2654,10 +2659,10 @@ public final class SatelliteManager { protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == SATELLITE_RESULT_SUCCESS) { if (resultData.containsKey(KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN)) { - List<SatelliteSubscriberInfo> list = + List<SatelliteSubscriberProvisionStatus> list = resultData.getParcelableArrayList( KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN, - SatelliteSubscriberInfo.class); + SatelliteSubscriberProvisionStatus.class); executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onResult(list))); } else { @@ -2672,70 +2677,14 @@ public final class SatelliteManager { } } }; - telephony.requestProvisionSubscriberIds(receiver); - } else { - loge("requestProvisionSubscriberIds() invalid telephony"); - executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( - new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); - } - } catch (RemoteException ex) { - loge("requestProvisionSubscriberIds() RemoteException: " + ex); - executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( - new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); - } - } - - /** - * Request to get provisioned status for given a satellite subscriber id. - * - * @param satelliteSubscriberId Satellite subscriber id requiring provisioned status check. - * @param executor The executor on which the callback will be called. - * @param callback callback. - * - * @throws SecurityException if the caller doesn't have required permission. - * @hide - */ - @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) - @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) - public void requestIsProvisioned(@NonNull String satelliteSubscriberId, - @NonNull @CallbackExecutor Executor executor, - @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { - Objects.requireNonNull(satelliteSubscriberId); - Objects.requireNonNull(executor); - Objects.requireNonNull(callback); - - try { - ITelephony telephony = getITelephony(); - if (telephony != null) { - ResultReceiver receiver = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - if (resultCode == SATELLITE_RESULT_SUCCESS) { - if (resultData.containsKey(KEY_IS_SATELLITE_PROVISIONED)) { - boolean isIsProvisioned = - resultData.getBoolean(KEY_IS_SATELLITE_PROVISIONED); - executor.execute(() -> Binder.withCleanCallingIdentity(() -> - callback.onResult(isIsProvisioned))); - } else { - loge("KEY_IS_SATELLITE_PROVISIONED does not exist."); - executor.execute(() -> Binder.withCleanCallingIdentity(() -> - callback.onError(new SatelliteException( - SATELLITE_RESULT_REQUEST_FAILED)))); - } - } else { - executor.execute(() -> Binder.withCleanCallingIdentity(() -> - callback.onError(new SatelliteException(resultCode)))); - } - } - }; - telephony.requestIsProvisioned(satelliteSubscriberId, receiver); + telephony.requestSatelliteSubscriberProvisionStatus(receiver); } else { - loge("requestIsSatelliteProvisioned() invalid telephony"); + loge("requestSatelliteSubscriberProvisionStatus() invalid telephony"); executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); } } catch (RemoteException ex) { - loge("requestIsSatelliteProvisioned() RemoteException: " + ex); + loge("requestSatelliteSubscriberProvisionStatus() RemoteException: " + ex); executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); } diff --git a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java index a12952be7620..e8ae0f56ee9e 100644 --- a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java +++ b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java @@ -17,10 +17,13 @@ package android.telephony.satellite; import android.annotation.FlaggedApi; +import android.annotation.NonNull; import android.annotation.SystemApi; import com.android.internal.telephony.flags.Flags; +import java.util.List; + /** * A callback class for monitoring satellite provision state change events. * @@ -39,4 +42,16 @@ public interface SatelliteProvisionStateCallback { */ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) void onSatelliteProvisionStateChanged(boolean provisioned); + + /** + * Called when the provisioning state of one or more SatelliteSubscriberInfos changes. + * + * @param satelliteSubscriberProvisionStatus The List contains the latest provisioning states + * of the SatelliteSubscriberInfos. + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + default void onSatelliteSubscriptionProvisionStateChanged( + @NonNull List<SatelliteSubscriberProvisionStatus> + satelliteSubscriberProvisionStatus) {}; } diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java index f26219bd0885..dbe5dddf8ce8 100644 --- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java +++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java @@ -17,12 +17,15 @@ package android.telephony.satellite; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.telephony.flags.Flags; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -39,25 +42,115 @@ public final class SatelliteSubscriberInfo implements Parcelable { /** provision subscriberId */ @NonNull private String mSubscriberId; - /** carrier id */ private int mCarrierId; /** apn */ private String mNiddApn; + private int mSubId; + + /** SubscriberId format is the ICCID. */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public static final int ICCID = 0; + /** SubscriberId format is the 6 digit of IMSI + MSISDN. */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public static final int IMSI_MSISDN = 1; + + /** Type of subscriber id */ + @SubscriberIdType private int mSubscriberIdType; + /** @hide */ + @IntDef(prefix = "SubscriberId_Type_", value = { + ICCID, + IMSI_MSISDN + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SubscriberIdType {} + + private SatelliteSubscriberInfo(Parcel in) { + readFromParcel(in); + } + + public SatelliteSubscriberInfo(@NonNull Builder builder) { + this.mSubscriberId = builder.mSubscriberId; + this.mCarrierId = builder.mCarrierId; + this.mNiddApn = builder.mNiddApn; + this.mSubId = builder.mSubId; + this.mSubscriberIdType = builder.mSubscriberIdType; + } /** + * Builder class for constructing SatelliteSubscriberInfo objects + * * @hide */ - public SatelliteSubscriberInfo(@NonNull String subscriberId, @NonNull int carrierId, - @NonNull String niddApn) { - this.mCarrierId = carrierId; - this.mSubscriberId = subscriberId; - this.mNiddApn = niddApn; - } + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public static class Builder { + @NonNull private String mSubscriberId; + private int mCarrierId; + @NonNull + private String mNiddApn; + private int mSubId; + @SubscriberIdType + private int mSubscriberIdType; - private SatelliteSubscriberInfo(Parcel in) { - readFromParcel(in); + /** + * Set the SubscriberId and returns the Builder class. + * + * @hide + */ + public Builder setSubscriberId(String subscriberId) { + mSubscriberId = subscriberId; + return this; + } + + /** + * Set the CarrierId and returns the Builder class. + * @hide + */ + @NonNull + public Builder setCarrierId(int carrierId) { + mCarrierId = carrierId; + return this; + } + + /** + * Set the niddApn and returns the Builder class. + * @hide + */ + @NonNull + public Builder setNiddApn(String niddApn) { + mNiddApn = niddApn; + return this; + } + + /** + * Set the subId and returns the Builder class. + * @hide + */ + @NonNull + public Builder setSubId(int subId) { + mSubId = subId; + return this; + } + + /** + * Set the SubscriberIdType and returns the Builder class. + * @hide + */ + @NonNull + public Builder setSubscriberIdType(@SubscriberIdType int subscriberIdType) { + mSubscriberIdType = subscriberIdType; + return this; + } + + /** + * Returns SatelliteSubscriberInfo object. + * @hide + */ + @NonNull + public SatelliteSubscriberInfo build() { + return new SatelliteSubscriberInfo(this); + } } /** @@ -69,6 +162,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { out.writeString(mSubscriberId); out.writeInt(mCarrierId); out.writeString(mNiddApn); + out.writeInt(mSubId); + out.writeInt(mSubscriberIdType); } @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) @@ -121,6 +216,24 @@ public final class SatelliteSubscriberInfo implements Parcelable { return mNiddApn; } + /** + * @return subId. + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public int getSubId() { + return mSubId; + } + + /** + * @return subscriberIdType. + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public @SubscriberIdType int getSubscriberIdType() { + return mSubscriberIdType; + } + @NonNull @Override public String toString() { @@ -136,26 +249,37 @@ public final class SatelliteSubscriberInfo implements Parcelable { sb.append("NiddApn:"); sb.append(mNiddApn); + sb.append(","); + + sb.append("SubId:"); + sb.append(mSubId); + sb.append(","); + + sb.append("SubscriberIdType:"); + sb.append(mSubscriberIdType); return sb.toString(); } @Override public int hashCode() { - return Objects.hash(mSubscriberId, mCarrierId, mNiddApn); + return Objects.hash(mSubscriberId, mCarrierId, mNiddApn, mSubId, mSubscriberIdType); } @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof SatelliteSubscriberInfo)) return false; SatelliteSubscriberInfo that = (SatelliteSubscriberInfo) o; - return mSubscriberId.equals(that.mSubscriberId) && mCarrierId - == that.mCarrierId && mNiddApn.equals(that.mNiddApn); + return Objects.equals(mSubscriberId, that.mSubscriberId) && mCarrierId == that.mCarrierId + && Objects.equals(mNiddApn, that.mNiddApn) && mSubId == that.mSubId + && mSubscriberIdType == that.mSubscriberIdType; } private void readFromParcel(Parcel in) { mSubscriberId = in.readString(); mCarrierId = in.readInt(); mNiddApn = in.readString(); + mSubId = in.readInt(); + mSubscriberIdType = in.readInt(); } } diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl new file mode 100644 index 000000000000..80de77905f80 --- /dev/null +++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2024, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.satellite; + +parcelable SatelliteSubscriberProvisionStatus;
\ No newline at end of file diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java new file mode 100644 index 000000000000..08ef3f2d8d12 --- /dev/null +++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.satellite; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.telephony.flags.Flags; + +import java.util.Objects; + +/** + * Represents the provisioning state of SatelliteSubscriberInfo. + * + * @hide + */ +@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) +public class SatelliteSubscriberProvisionStatus implements Parcelable { + private SatelliteSubscriberInfo mSubscriberInfo; + /** {@code true} mean the satellite subscriber is provisioned, {@code false} otherwise. */ + private boolean mProvisionStatus; + + public SatelliteSubscriberProvisionStatus(@NonNull Builder builder) { + mSubscriberInfo = builder.mSubscriberInfo; + mProvisionStatus = builder.mProvisionStatus; + } + + /** + * Builder class for constructing SatelliteSubscriberProvisionStatus objects + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public static class Builder { + private SatelliteSubscriberInfo mSubscriberInfo; + private boolean mProvisionStatus; + + /** + * Set the SatelliteSubscriberInfo and returns the Builder class. + * @hide + */ + public Builder setSatelliteSubscriberInfo(SatelliteSubscriberInfo satelliteSubscriberInfo) { + mSubscriberInfo = satelliteSubscriberInfo; + return this; + } + + /** + * Set the SatelliteSubscriberInfo's provisionStatus and returns the Builder class. + * @hide + */ + @NonNull + public Builder setProvisionStatus(boolean provisionStatus) { + mProvisionStatus = provisionStatus; + return this; + } + + /** + * Returns SatelliteSubscriberProvisionStatus object. + * @hide + */ + @NonNull + public SatelliteSubscriberProvisionStatus build() { + return new SatelliteSubscriberProvisionStatus(this); + } + } + + private SatelliteSubscriberProvisionStatus(Parcel in) { + readFromParcel(in); + } + + /** + * @hide + */ + @Override + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mSubscriberInfo, flags); + out.writeBoolean(mProvisionStatus); + } + + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public static final @android.annotation.NonNull Creator<SatelliteSubscriberProvisionStatus> + CREATOR = + new Creator<SatelliteSubscriberProvisionStatus>() { + @Override + public SatelliteSubscriberProvisionStatus createFromParcel(Parcel in) { + return new SatelliteSubscriberProvisionStatus(in); + } + + @Override + public SatelliteSubscriberProvisionStatus[] newArray(int size) { + return new SatelliteSubscriberProvisionStatus[size]; + } + }; + + /** + * @hide + */ + @Override + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public int describeContents() { + return 0; + } + + /** + * SatelliteSubscriberInfo that has a provisioning state. + * @return SatelliteSubscriberInfo. + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public @NonNull SatelliteSubscriberInfo getSatelliteSubscriberInfo() { + return mSubscriberInfo; + } + + /** + * SatelliteSubscriberInfo's provisioning state. + * @return {@code true} means provisioning. {@code false} means deprovisioning. + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public @NonNull boolean getProvisionStatus() { + return mProvisionStatus; + } + + @NonNull + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("SatelliteSubscriberInfo:"); + sb.append(mSubscriberInfo); + sb.append(","); + + sb.append("ProvisionStatus:"); + sb.append(mProvisionStatus); + return sb.toString(); + } + + @Override + public int hashCode() { + return Objects.hash(mSubscriberInfo, mProvisionStatus); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SatelliteSubscriberProvisionStatus)) return false; + SatelliteSubscriberProvisionStatus that = (SatelliteSubscriberProvisionStatus) o; + return Objects.equals(mSubscriberInfo, that.mSubscriberInfo) + && mProvisionStatus == that.mProvisionStatus; + } + + private void readFromParcel(Parcel in) { + mSubscriberInfo = in.readParcelable(SatelliteSubscriberInfo.class.getClassLoader(), + SatelliteSubscriberInfo.class); + mProvisionStatus = in.readBoolean(); + } +} diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 89197032dcef..0c5f30f96360 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -3413,19 +3413,7 @@ interface ITelephony { */ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + "android.Manifest.permission.SATELLITE_COMMUNICATION)") - void requestProvisionSubscriberIds(in ResultReceiver result); - - /** - * Request to get provisioned status for given a satellite subscriber id. - * - * @param satelliteSubscriberId Satellite subscriber id requiring provisioned status check. - * @param result The result receiver, which returns the provisioned status of the token if the - * request is successful or an error code if the request failed. - * @hide - */ - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" - + "android.Manifest.permission.SATELLITE_COMMUNICATION)") - void requestIsProvisioned(in String satelliteSubscriberId, in ResultReceiver result); + void requestSatelliteSubscriberProvisionStatus(in ResultReceiver result); /** * Deliver the list of provisioned satellite subscriber infos. diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt index 638d594b0a48..eb63e4985a9f 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt @@ -28,6 +28,7 @@ import com.android.server.wm.flicker.BaseTest import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd +import com.android.server.wm.flicker.taskBarLayerIsVisibleAtStartAndEnd import org.junit.Assume import org.junit.FixMethodOrder import org.junit.Ignore @@ -114,28 +115,28 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl /** * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions - * this is fixed and the nav bar shows as invisible + * this is fixed and the status bar shows as invisible */ @Presubmit @Test fun statusBarLayerIsInvisibleInLandscapePhone() { Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) Assume.assumeTrue(flicker.scenario.isGesturalNavigation) - Assume.assumeFalse(usesTaskbar) + Assume.assumeFalse(flicker.scenario.isTablet) flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) } flicker.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) } } /** * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions - * this is fixed and the nav bar shows as invisible + * this is fixed and the status bar shows as invisible */ @Presubmit @Test fun statusBarLayerIsInvisibleInLandscapeTablet() { Assume.assumeTrue(flicker.scenario.isLandscapeOrSeascapeAtStart) Assume.assumeTrue(flicker.scenario.isGesturalNavigation) - Assume.assumeTrue(usesTaskbar) + Assume.assumeTrue(flicker.scenario.isTablet) flicker.statusBarLayerIsVisibleAtStartAndEnd() } @@ -149,6 +150,10 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl @Ignore("Visibility changes depending on orientation and navigation mode") override fun navBarLayerPositionAtStartAndEnd() {} + @Test + @Ignore("Visibility changes depending on orientation and navigation mode") + override fun taskBarLayerIsVisibleAtStartAndEnd() {} + /** {@inheritDoc} */ @Test @Ignore("Visibility changes depending on orientation and navigation mode") @@ -161,7 +166,10 @@ class ShowImeWhileEnteringOverviewTest(flicker: LegacyFlickerTest) : BaseTest(fl @Presubmit @Test - override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd() + fun taskBarLayerIsVisibleAtStartAndEndForTablets() { + Assume.assumeTrue(flicker.scenario.isTablet) + flicker.taskBarLayerIsVisibleAtStartAndEnd() + } @Presubmit @Test diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt index 70d762e02af5..851ce022bd81 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt @@ -137,8 +137,6 @@ constructor( /** * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of the * transition - * - * Note: Large screen only */ @Presubmit @Test @@ -149,8 +147,6 @@ constructor( /** * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole transition - * - * Note: Large screen only */ @Presubmit @Test diff --git a/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt index 24d7291bec87..14aac6637d4f 100644 --- a/tests/Input/src/android/hardware/input/KeyboardSystemShortcutListenerTest.kt +++ b/tests/Input/src/android/hardware/input/KeyGestureEventListenerTest.kt @@ -42,21 +42,22 @@ import kotlin.test.assertNull import kotlin.test.fail /** - * Tests for [InputManager.KeyboardSystemShortcutListener]. + * Tests for [InputManager.KeyGestureEventListener]. * * Build/Install/Run: - * atest InputTests:KeyboardSystemShortcutListenerTest + * atest InputTests:KeyGestureEventListenerTest */ @Presubmit @RunWith(MockitoJUnitRunner::class) -class KeyboardSystemShortcutListenerTest { +class KeyGestureEventListenerTest { companion object { const val DEVICE_ID = 1 - val HOME_SHORTCUT = KeyboardSystemShortcut( + val HOME_GESTURE_EVENT = KeyGestureEvent( + DEVICE_ID, intArrayOf(KeyEvent.KEYCODE_H), KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME + KeyGestureEvent.KEY_GESTURE_TYPE_HOME ) } @@ -65,7 +66,7 @@ class KeyboardSystemShortcutListenerTest { private val testLooper = TestLooper() private val executor = HandlerExecutor(Handler(testLooper.looper)) - private var registeredListener: IKeyboardSystemShortcutListener? = null + private var registeredListener: IKeyGestureEventListener? = null private lateinit var context: Context private lateinit var inputManager: InputManager private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession @@ -81,28 +82,28 @@ class KeyboardSystemShortcutListenerTest { `when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE))) .thenReturn(inputManager) - // Handle keyboard system shortcut listener registration. + // Handle key gesture event listener registration. doAnswer { - val listener = it.getArgument(0) as IKeyboardSystemShortcutListener + val listener = it.getArgument(0) as IKeyGestureEventListener if (registeredListener != null && registeredListener!!.asBinder() != listener.asBinder()) { - // There can only be one registered keyboard system shortcut listener per process. + // There can only be one registered key gesture event listener per process. fail("Trying to register a new listener when one already exists") } registeredListener = listener null - }.`when`(iInputManagerMock).registerKeyboardSystemShortcutListener(any()) + }.`when`(iInputManagerMock).registerKeyGestureEventListener(any()) - // Handle keyboard system shortcut listener being unregistered. + // Handle key gesture event listener being unregistered. doAnswer { - val listener = it.getArgument(0) as IKeyboardSystemShortcutListener + val listener = it.getArgument(0) as IKeyGestureEventListener if (registeredListener == null || registeredListener!!.asBinder() != listener.asBinder()) { fail("Trying to unregister a listener that is not registered") } registeredListener = null null - }.`when`(iInputManagerMock).unregisterKeyboardSystemShortcutListener(any()) + }.`when`(iInputManagerMock).unregisterKeyGestureEventListener(any()) } @After @@ -112,29 +113,28 @@ class KeyboardSystemShortcutListenerTest { } } - private fun notifyKeyboardSystemShortcutTriggered(id: Int, shortcut: KeyboardSystemShortcut) { - registeredListener!!.onKeyboardSystemShortcutTriggered( - id, - shortcut.keycodes, - shortcut.modifierState, - shortcut.systemShortcut + private fun notifyKeyGestureEvent(event: KeyGestureEvent) { + registeredListener!!.onKeyGestureEvent( + event.deviceId, + event.keycodes, + event.modifierState, + event.keyGestureType ) } @Test - fun testListenerHasCorrectSystemShortcutNotified() { + fun testListenerHasCorrectGestureNotified() { var callbackCount = 0 - // Add a keyboard system shortcut listener - inputManager.registerKeyboardSystemShortcutListener(executor) { - deviceId: Int, systemShortcut: KeyboardSystemShortcut -> - assertEquals(DEVICE_ID, deviceId) - assertEquals(HOME_SHORTCUT, systemShortcut) + // Add a key gesture event listener + inputManager.registerKeyGestureEventListener(executor) { + event: KeyGestureEvent -> + assertEquals(HOME_GESTURE_EVENT, event) callbackCount++ } - // Notifying keyboard system shortcut triggered will notify the listener. - notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT) + // Notifying key gesture event will notify the listener. + notifyKeyGestureEvent(HOME_GESTURE_EVENT) testLooper.dispatchNext() assertEquals(1, callbackCount) } @@ -142,34 +142,34 @@ class KeyboardSystemShortcutListenerTest { @Test fun testAddingListenersRegistersInternalCallbackListener() { // Set up two callbacks. - val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> } - val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> } + val callback1 = InputManager.KeyGestureEventListener { _ -> } + val callback2 = InputManager.KeyGestureEventListener { _ -> } assertNull(registeredListener) // Adding the listener should register the callback with InputManagerService. - inputManager.registerKeyboardSystemShortcutListener(executor, callback1) + inputManager.registerKeyGestureEventListener(executor, callback1) assertNotNull(registeredListener) // Adding another listener should not register new internal listener. val currListener = registeredListener - inputManager.registerKeyboardSystemShortcutListener(executor, callback2) + inputManager.registerKeyGestureEventListener(executor, callback2) assertEquals(currListener, registeredListener) } @Test fun testRemovingListenersUnregistersInternalCallbackListener() { // Set up two callbacks. - val callback1 = InputManager.KeyboardSystemShortcutListener {_, _ -> } - val callback2 = InputManager.KeyboardSystemShortcutListener {_, _ -> } + val callback1 = InputManager.KeyGestureEventListener { _ -> } + val callback2 = InputManager.KeyGestureEventListener { _ -> } - inputManager.registerKeyboardSystemShortcutListener(executor, callback1) - inputManager.registerKeyboardSystemShortcutListener(executor, callback2) + inputManager.registerKeyGestureEventListener(executor, callback1) + inputManager.registerKeyGestureEventListener(executor, callback2) // Only removing all listeners should remove the internal callback - inputManager.unregisterKeyboardSystemShortcutListener(callback1) + inputManager.unregisterKeyGestureEventListener(callback1) assertNotNull(registeredListener) - inputManager.unregisterKeyboardSystemShortcutListener(callback2) + inputManager.unregisterKeyGestureEventListener(callback2) assertNull(registeredListener) } @@ -178,23 +178,23 @@ class KeyboardSystemShortcutListenerTest { // Set up two callbacks. var callbackCount1 = 0 var callbackCount2 = 0 - val callback1 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount1++ } - val callback2 = InputManager.KeyboardSystemShortcutListener { _, _ -> callbackCount2++ } + val callback1 = InputManager.KeyGestureEventListener { _ -> callbackCount1++ } + val callback2 = InputManager.KeyGestureEventListener { _ -> callbackCount2++ } - // Add both keyboard system shortcut listeners - inputManager.registerKeyboardSystemShortcutListener(executor, callback1) - inputManager.registerKeyboardSystemShortcutListener(executor, callback2) + // Add both key gesture event listeners + inputManager.registerKeyGestureEventListener(executor, callback1) + inputManager.registerKeyGestureEventListener(executor, callback2) - // Notifying keyboard system shortcut triggered, should notify both the callbacks. - notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT) + // Notifying key gesture event, should notify both the callbacks. + notifyKeyGestureEvent(HOME_GESTURE_EVENT) testLooper.dispatchAll() assertEquals(1, callbackCount1) assertEquals(1, callbackCount2) - inputManager.unregisterKeyboardSystemShortcutListener(callback2) - // Notifying keyboard system shortcut triggered, should still trigger callback1 but not + inputManager.unregisterKeyGestureEventListener(callback2) + // Notifying key gesture event, should still trigger callback1 but not // callback2. - notifyKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT) + notifyKeyGestureEvent(HOME_GESTURE_EVENT) testLooper.dispatchAll() assertEquals(2, callbackCount1) assertEquals(1, callbackCount2) diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt index 3c72498082e4..8829f74f5092 100644 --- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt +++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt @@ -151,6 +151,7 @@ class InputManagerServiceTests { verify(native).setTouchpadNaturalScrollingEnabled(anyBoolean()) verify(native).setTouchpadTapToClickEnabled(anyBoolean()) verify(native).setTouchpadTapDraggingEnabled(anyBoolean()) + verify(native).setShouldNotifyTouchpadHardwareState(anyBoolean()) verify(native).setTouchpadRightClickZoneEnabled(anyBoolean()) verify(native).setShowTouches(anyBoolean()) verify(native).setMotionClassifierEnabled(anyBoolean()) diff --git a/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt index 5a40a1c8201e..3f611e0ead53 100644 --- a/tests/Input/src/com/android/server/input/KeyboardShortcutCallbackHandlerTests.kt +++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt @@ -18,8 +18,8 @@ package com.android.server.input import android.content.Context import android.content.ContextWrapper -import android.hardware.input.IKeyboardSystemShortcutListener -import android.hardware.input.KeyboardSystemShortcut +import android.hardware.input.IKeyGestureEventListener +import android.hardware.input.KeyGestureEvent import android.platform.test.annotations.Presubmit import android.view.KeyEvent import androidx.test.core.app.ApplicationProvider @@ -32,65 +32,65 @@ import org.mockito.Mockito import org.mockito.junit.MockitoJUnit /** - * Tests for {@link KeyboardShortcutCallbackHandler}. + * Tests for {@link KeyGestureController}. * * Build/Install/Run: - * atest InputTests:KeyboardShortcutCallbackHandlerTests + * atest InputTests:KeyGestureControllerTests */ @Presubmit -class KeyboardShortcutCallbackHandlerTests { +class KeyGestureControllerTests { companion object { val DEVICE_ID = 1 - val HOME_SHORTCUT = KeyboardSystemShortcut( + val HOME_GESTURE_EVENT = KeyGestureEvent( + DEVICE_ID, intArrayOf(KeyEvent.KEYCODE_H), KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON, - KeyboardSystemShortcut.SYSTEM_SHORTCUT_HOME + KeyGestureEvent.KEY_GESTURE_TYPE_HOME ) } @get:Rule val rule = MockitoJUnit.rule()!! - private lateinit var keyboardShortcutCallbackHandler: KeyboardShortcutCallbackHandler + private lateinit var keyGestureController: KeyGestureController private lateinit var context: Context - private var lastShortcut: KeyboardSystemShortcut? = null + private var lastEvent: KeyGestureEvent? = null @Before fun setup() { context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext())) - keyboardShortcutCallbackHandler = KeyboardShortcutCallbackHandler() + keyGestureController = KeyGestureController() } @Test - fun testKeyboardSystemShortcutTriggered_registerUnregisterListener() { - val listener = KeyboardSystemShortcutListener() + fun testKeyGestureEvent_registerUnregisterListener() { + val listener = KeyGestureEventListener() - // Register keyboard system shortcut listener - keyboardShortcutCallbackHandler.registerKeyboardSystemShortcutListener(listener, 0) - keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT) + // Register key gesture event listener + keyGestureController.registerKeyGestureEventListener(listener, 0) + keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT) assertEquals( - "Listener should get callback on keyboard system shortcut triggered", - HOME_SHORTCUT, - lastShortcut!! + "Listener should get callback on key gesture event", + HOME_GESTURE_EVENT, + lastEvent!! ) // Unregister listener - lastShortcut = null - keyboardShortcutCallbackHandler.unregisterKeyboardSystemShortcutListener(listener, 0) - keyboardShortcutCallbackHandler.onKeyboardSystemShortcutTriggered(DEVICE_ID, HOME_SHORTCUT) - assertNull("Listener should not get callback after being unregistered", lastShortcut) + lastEvent = null + keyGestureController.unregisterKeyGestureEventListener(listener, 0) + keyGestureController.onKeyGestureEvent(HOME_GESTURE_EVENT) + assertNull("Listener should not get callback after being unregistered", lastEvent) } - inner class KeyboardSystemShortcutListener : IKeyboardSystemShortcutListener.Stub() { - override fun onKeyboardSystemShortcutTriggered( + inner class KeyGestureEventListener : IKeyGestureEventListener.Stub() { + override fun onKeyGestureEvent( deviceId: Int, keycodes: IntArray, modifierState: Int, - shortcut: Int + gestureType: Int ) { - assertEquals(DEVICE_ID, deviceId) - lastShortcut = KeyboardSystemShortcut(keycodes, modifierState, shortcut) + lastEvent = KeyGestureEvent(deviceId, keycodes, modifierState, gestureType) } } }
\ No newline at end of file diff --git a/tests/Internal/AndroidTest.xml b/tests/Internal/AndroidTest.xml index 7b67e9ebcced..2d6c650eb2dc 100644 --- a/tests/Internal/AndroidTest.xml +++ b/tests/Internal/AndroidTest.xml @@ -26,4 +26,12 @@ <option name="package" value="com.android.internal.tests" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> </test> + + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path"/> + <option name="directory-keys" + value="/data/user/0/com.android.internal.tests/files"/> + <option name="collect-on-run-ended-only" value="true"/> + <option name="clean-up" value="true"/> + </metrics_collector> </configuration>
\ No newline at end of file diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java index 5a48327e7576..9657225588b7 100644 --- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java +++ b/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java @@ -214,6 +214,13 @@ public class LegacyProtoLogImplTest { verify(mReader, never()).getViewerString(anyLong()); } + @Test + public void loadViewerConfigOnLogcatGroupRegistration() { + TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true); + mProtoLog.registerGroups(TestProtoLogGroup.TEST_GROUP); + verify(mReader).loadViewerConfig(any(), any()); + } + private static class ProtoLogData { Long mMessageHash = null; Long mElapsedTime = null; diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java index 7d0c5966b5dc..4b745b289d33 100644 --- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java +++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java @@ -29,7 +29,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static java.io.File.createTempFile; -import static java.nio.file.Files.createTempDirectory; import android.content.Context; import android.os.SystemClock; @@ -45,6 +44,7 @@ import android.tracing.perfetto.DataSource; import android.util.proto.ProtoInputStream; import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.protolog.common.IProtoLogGroup; import com.android.internal.protolog.common.LogDataType; @@ -67,7 +67,6 @@ import java.io.File; import java.io.IOException; import java.util.List; import java.util.Random; -import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; /** @@ -78,7 +77,8 @@ import java.util.concurrent.atomic.AtomicInteger; @Presubmit @RunWith(JUnit4.class) public class PerfettoProtoLogImplTest { - private final File mTracingDirectory = createTempDirectory("temp").toFile(); + private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation() + .getTargetContext().getFilesDir(); private final ResultWriter mWriter = new ResultWriter() .forScenario(new ScenarioBuilder() @@ -384,7 +384,7 @@ public class PerfettoProtoLogImplTest { new Object[]{5}); verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( - LogLevel.INFO), eq("UNKNOWN MESSAGE#1234 (5)")); + LogLevel.INFO), eq("UNKNOWN MESSAGE args = (5)")); verify(mReader).getViewerString(eq(1234L)); } @@ -451,8 +451,8 @@ public class PerfettoProtoLogImplTest { before = SystemClock.elapsedRealtimeNanos(); mProtoLog.log( LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, - "My test message :: %s, %d, %o, %x, %f, %b", - "test", 1, 2, 3, 0.4, true); + "My test message :: %s, %d, %x, %f, %b", + "test", 1, 3, 0.4, true); after = SystemClock.elapsedRealtimeNanos(); } finally { traceMonitor.stop(mWriter); @@ -467,7 +467,7 @@ public class PerfettoProtoLogImplTest { Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos()) .isAtMost(after); Truth.assertThat(protolog.messages.getFirst().getMessage()) - .isEqualTo("My test message :: test, 2, 4, 6, 0.400000, true"); + .isEqualTo("My test message :: test, 2, 6, 0.400000, true"); } @Test diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java index 359eb35384c7..5012c235a2a5 100644 --- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java +++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostSyncTest.java @@ -84,6 +84,7 @@ public class SurfaceControlViewHostSyncTest extends Activity implements SurfaceH content.addView(enableSyncButton, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM)); + content.setFitsSystemWindows(true); setContentView(content); mSv.setZOrderOnTop(false); diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java index 73e01634709e..4119ea2c73c3 100644 --- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java +++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java @@ -37,6 +37,7 @@ public class SurfaceControlViewHostTest extends Activity implements SurfaceHolde protected void onCreate(Bundle savedInstanceState) { FrameLayout content = new FrameLayout(this); + content.setFitsSystemWindows(true); super.onCreate(savedInstanceState); mView = new SurfaceView(this); content.addView(mView, new FrameLayout.LayoutParams( diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java index ac7dc9e2f31f..528706860b31 100644 --- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java +++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceInputTestActivity.java @@ -88,6 +88,7 @@ public class SurfaceInputTestActivity extends Activity { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout content = new LinearLayout(this); + content.setFitsSystemWindows(true); mLocalSurfaceView = new SurfaceView(this); content.addView(mLocalSurfaceView, new LinearLayout.LayoutParams( 500, 500, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java index 09236ffebdf4..459db8a0a1ac 100644 --- a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java @@ -74,6 +74,9 @@ public class BitmapUploadActivity extends AppCompatActivity { } } + private ObjectAnimator mColorValueAnimator; + private ObjectAnimator mYAnimator; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -81,16 +84,28 @@ public class BitmapUploadActivity extends AppCompatActivity { // animate color to force bitmap uploads UploadView uploadView = findViewById(R.id.upload_view); - ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255); - colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE); - colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE); - colorValueAnimator.start(); + mColorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255); + mColorValueAnimator.setRepeatMode(ValueAnimator.REVERSE); + mColorValueAnimator.setRepeatCount(ValueAnimator.INFINITE); + mColorValueAnimator.start(); // animate scene root to guarantee there's a minimum amount of GPU rendering work View uploadRoot = findViewById(R.id.upload_root); - ObjectAnimator yAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100); - yAnimator.setRepeatMode(ValueAnimator.REVERSE); - yAnimator.setRepeatCount(ValueAnimator.INFINITE); - yAnimator.start(); + mYAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100); + mYAnimator.setRepeatMode(ValueAnimator.REVERSE); + mYAnimator.setRepeatCount(ValueAnimator.INFINITE); + mYAnimator.start(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mColorValueAnimator != null) { + mColorValueAnimator.cancel(); + } + + if (mYAnimator != null) { + mYAnimator.cancel(); + } } } diff --git a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java index 882163bd6b0e..9d10f76198c3 100644 --- a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java @@ -66,18 +66,29 @@ public class FullscreenOverdrawActivity extends AppCompatActivity { return PixelFormat.OPAQUE; } } + + private ObjectAnimator mObjectAnimator; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); OverdrawDrawable overdraw = new OverdrawDrawable(); getWindow().setBackgroundDrawable(overdraw); - setContentView(new View(this)); - ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdraw, "colorValue", 0, 255); - objectAnimator.setRepeatMode(ValueAnimator.REVERSE); - objectAnimator.setRepeatCount(ValueAnimator.INFINITE); - objectAnimator.start(); + mObjectAnimator = ObjectAnimator.ofInt(overdraw, "colorValue", 0, 255); + mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE); + mObjectAnimator.setRepeatCount(ValueAnimator.INFINITE); + + mObjectAnimator.start(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mObjectAnimator != null) { + mObjectAnimator.cancel(); + } } } diff --git a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java index b26a660981da..1b28dc29d6aa 100644 --- a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java @@ -33,6 +33,7 @@ import com.android.test.uibench.opengl.ImageFlipRenderThread; public class GlTextureViewActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { private ImageFlipRenderThread mRenderThread; private TextureView mTextureView; + private ObjectAnimator mAnimator; @Override protected void onCreate(Bundle savedInstanceState) { @@ -54,17 +55,17 @@ public class GlTextureViewActivity extends AppCompatActivity implements TextureV int distance = Math.max(mTextureView.getWidth(), mTextureView.getHeight()); mTextureView.setCameraDistance(distance * metrics.density); - ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); - animator.setRepeatMode(ObjectAnimator.REVERSE); - animator.setRepeatCount(ObjectAnimator.INFINITE); - animator.setDuration(4000); - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + mAnimator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); + mAnimator.setRepeatMode(ObjectAnimator.REVERSE); + mAnimator.setRepeatCount(ObjectAnimator.INFINITE); + mAnimator.setDuration(4000); + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mTextureView.invalidate(); } }); - animator.start(); + mAnimator.start(); } @Override @@ -86,4 +87,11 @@ public class GlTextureViewActivity extends AppCompatActivity implements TextureV public void onSurfaceTextureUpdated(SurfaceTexture surface) { } + @Override + protected void onPause() { + super.onPause(); + if (mAnimator != null) { + mAnimator.cancel(); + } + } }
\ No newline at end of file diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java index 76ed1ae4e445..f1e96c80c85a 100644 --- a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java @@ -51,6 +51,7 @@ public class InvalidateActivity extends AppCompatActivity { } private ColorView[][] mColorViews; + private ObjectAnimator mAnimator; @SuppressWarnings("unused") public void setColorValue(int colorValue) { @@ -80,9 +81,17 @@ public class InvalidateActivity extends AppCompatActivity { } } - ObjectAnimator animator = ObjectAnimator.ofInt(this, "colorValue", 0, 255); - animator.setRepeatMode(ValueAnimator.REVERSE); - animator.setRepeatCount(ValueAnimator.INFINITE); - animator.start(); + mAnimator = ObjectAnimator.ofInt(this, "colorValue", 0, 255); + mAnimator.setRepeatMode(ValueAnimator.REVERSE); + mAnimator.setRepeatCount(ValueAnimator.INFINITE); + mAnimator.start(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mAnimator != null) { + mAnimator.cancel(); + } } } diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java index 804ced14d522..95635720d4f9 100644 --- a/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java +++ b/tests/UiBench/src/com/android/test/uibench/InvalidateTreeActivity.java @@ -33,6 +33,7 @@ public class InvalidateTreeActivity extends AppCompatActivity { private final ArrayList<LinearLayout> mLayouts = new ArrayList<>(); private int mColorToggle = 0; + private ObjectAnimator mAnimator; private void createQuadTree(LinearLayout parent, int remainingDepth) { mLayouts.add(parent); @@ -71,9 +72,17 @@ public class InvalidateTreeActivity extends AppCompatActivity { createQuadTree(root, 8); setContentView(root); - ObjectAnimator animator = ObjectAnimator.ofInt(this, "ignoredValue", 0, 1000); - animator.setRepeatMode(ValueAnimator.REVERSE); - animator.setRepeatCount(ValueAnimator.INFINITE); - animator.start(); + mAnimator = ObjectAnimator.ofInt(this, "ignoredValue", 0, 1000); + mAnimator.setRepeatMode(ValueAnimator.REVERSE); + mAnimator.setRepeatCount(ValueAnimator.INFINITE); + mAnimator.start(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mAnimator != null) { + mAnimator.cancel(); + } } } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 1c85e9ff231b..a5aecc855707 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -151,6 +151,7 @@ static bool AddResourcesToTable(ResourceTable* table, android::IDiagnostics* dia } if (res->value != nullptr) { + res->value->SetFlagStatus(res->flag_status); // Attach the comment, source and config to the value. res->value->SetComment(std::move(res->comment)); res->value->SetSource(std::move(res->source)); @@ -546,30 +547,11 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, }); std::string resource_type = parser->element_name(); - std::optional<StringPiece> flag = - xml::FindAttribute(parser, "http://schemas.android.com/apk/res/android", "featureFlag"); - out_resource->flag_status = FlagStatus::NoFlag; - if (flag) { - auto flag_it = options_.feature_flag_values.find(flag.value()); - if (flag_it == options_.feature_flag_values.end()) { - diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) - << "Resource flag value undefined"); - return false; - } - const auto& flag_properties = flag_it->second; - if (!flag_properties.read_only) { - diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) - << "Only read only flags may be used with resources"); - return false; - } - if (!flag_properties.enabled.has_value()) { - diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) - << "Only flags with a value may be used with resources"); - return false; - } - out_resource->flag_status = - flag_properties.enabled.value() ? FlagStatus::Enabled : FlagStatus::Disabled; + auto flag_status = GetFlagStatus(parser); + if (!flag_status) { + return false; } + out_resource->flag_status = flag_status.value(); // The value format accepted for this resource. uint32_t resource_format = 0u; @@ -751,6 +733,33 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, return false; } +std::optional<FlagStatus> ResourceParser::GetFlagStatus(xml::XmlPullParser* parser) { + auto flag_status = FlagStatus::NoFlag; + + std::optional<StringPiece> flag = xml::FindAttribute(parser, xml::kSchemaAndroid, "featureFlag"); + if (flag) { + auto flag_it = options_.feature_flag_values.find(flag.value()); + if (flag_it == options_.feature_flag_values.end()) { + diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) + << "Resource flag value undefined"); + return {}; + } + const auto& flag_properties = flag_it->second; + if (!flag_properties.read_only) { + diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) + << "Only read only flags may be used with resources"); + return {}; + } + if (!flag_properties.enabled.has_value()) { + diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) + << "Only flags with a value may be used with resources"); + return {}; + } + flag_status = flag_properties.enabled.value() ? FlagStatus::Enabled : FlagStatus::Disabled; + } + return flag_status; +} + bool ResourceParser::ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource, const uint32_t format) { @@ -1657,12 +1666,18 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser, const std::string& element_namespace = parser->element_namespace(); const std::string& element_name = parser->element_name(); if (element_namespace.empty() && element_name == "item") { + auto flag_status = GetFlagStatus(parser); + if (!flag_status) { + error = true; + continue; + } std::unique_ptr<Item> item = ParseXml(parser, typeMask, kNoRawString); if (!item) { diag_->Error(android::DiagMessage(item_source) << "could not parse array item"); error = true; continue; } + item->SetFlagStatus(flag_status.value()); item->SetSource(item_source); array->elements.emplace_back(std::move(item)); diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h index 45d41c193cb4..442dea89ef40 100644 --- a/tools/aapt2/ResourceParser.h +++ b/tools/aapt2/ResourceParser.h @@ -85,6 +85,8 @@ class ResourceParser { private: DISALLOW_COPY_AND_ASSIGN(ResourceParser); + std::optional<FlagStatus> GetFlagStatus(xml::XmlPullParser* parser); + std::optional<FlattenedXmlSubTree> CreateFlattenSubTree(xml::XmlPullParser* parser); // Parses the XML subtree as a StyleString (flattened XML representation for strings with diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 1cdb71551d5d..7a4f40e471d2 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -605,12 +605,12 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag) if (!config_value->value) { // Resource does not exist, add it now. config_value->value = std::move(res.value); - config_value->flag_status = res.flag_status; } else { // When validation is enabled, ensure that a resource cannot have multiple values defined for // the same configuration unless protected by flags. - auto result = validate ? ResolveFlagCollision(config_value->flag_status, res.flag_status) - : CollisionResult::kKeepBoth; + auto result = + validate ? ResolveFlagCollision(config_value->value->GetFlagStatus(), res.flag_status) + : CollisionResult::kKeepBoth; if (result == CollisionResult::kConflict) { result = ResolveValueCollision(config_value->value.get(), res.value.get()); } @@ -619,7 +619,6 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag) // Insert the value ignoring for duplicate configurations entry->values.push_back(util::make_unique<ResourceConfigValue>(res.config, res.product)); entry->values.back()->value = std::move(res.value); - entry->values.back()->flag_status = res.flag_status; break; case CollisionResult::kTakeNew: diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 4f76e7d3a2b7..cba6b70cfbd6 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -104,8 +104,6 @@ class ResourceConfigValue { // The actual Value. std::unique_ptr<Value> value; - FlagStatus flag_status = FlagStatus::NoFlag; - ResourceConfigValue(const android::ConfigDescription& config, android::StringPiece product) : config(config), product(product) { } diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index 166b01bd9154..b75e87c90128 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -971,6 +971,16 @@ void Array::Print(std::ostream* out) const { *out << "(array) [" << util::Joiner(elements, ", ") << "]"; } +void Array::RemoveFlagDisabledElements() { + const auto end_iter = elements.end(); + const auto remove_iter = std::stable_partition( + elements.begin(), end_iter, [](const std::unique_ptr<Item>& item) -> bool { + return item->GetFlagStatus() != FlagStatus::Disabled; + }); + + elements.erase(remove_iter, end_iter); +} + bool Plural::Equals(const Value* value) const { const Plural* other = ValueCast<Plural>(value); if (!other) { @@ -1092,6 +1102,7 @@ template <typename T> std::unique_ptr<T> CopyValueFields(std::unique_ptr<T> new_value, const T* value) { new_value->SetSource(value->GetSource()); new_value->SetComment(value->GetComment()); + new_value->SetFlagStatus(value->GetFlagStatus()); return new_value; } diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index 5192c2be1f98..a1b1839b19ef 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -65,6 +65,14 @@ class Value { return translatable_; } + void SetFlagStatus(FlagStatus val) { + flag_status_ = val; + } + + FlagStatus GetFlagStatus() const { + return flag_status_; + } + // Returns the source where this value was defined. const android::Source& GetSource() const { return source_; @@ -109,6 +117,10 @@ class Value { // of brevity and readability. Default implementation just calls Print(). virtual void PrettyPrint(text::Printer* printer) const; + // Removes any part of the value that is beind a disabled flag. + virtual void RemoveFlagDisabledElements() { + } + friend std::ostream& operator<<(std::ostream& out, const Value& value); protected: @@ -116,6 +128,7 @@ class Value { std::string comment_; bool weak_ = false; bool translatable_ = true; + FlagStatus flag_status_ = FlagStatus::NoFlag; private: virtual Value* TransformValueImpl(ValueTransformer& transformer) const = 0; @@ -346,6 +359,7 @@ struct Array : public TransformableValue<Array, BaseValue<Array>> { bool Equals(const Value* value) const override; void Print(std::ostream* out) const override; + void RemoveFlagDisabledElements() override; }; struct Plural : public TransformableValue<Plural, BaseValue<Plural>> { diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 2ecc82ae4792..5c6408940b34 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -246,7 +246,7 @@ message Entry { message ConfigValue { Configuration config = 1; Value value = 2; - uint32 flag_status = 3; + reserved 3; } // The generic meta-data for every value in a resource table. @@ -280,6 +280,9 @@ message Item { Id id = 6; Primitive prim = 7; } + + // The status of the flag the value is behind if any + uint32 flag_status = 8; } // A CompoundValue is an abstract type. It represents a value that is a made of other values. diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 56f52885b36d..be63f82b30cf 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1878,7 +1878,7 @@ class Linker { for (auto& type : package->types) { for (auto& entry : type->entries) { for (auto& config_value : entry->values) { - if (config_value->flag_status == FlagStatus::Disabled) { + if (config_value->value->GetFlagStatus() == FlagStatus::Disabled) { config_value->value->Accept(&visitor); } } diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index aaab3158f61e..55f5e5668a16 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -534,8 +534,6 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr return false; } - config_value->flag_status = (FlagStatus)pb_config_value.flag_status(); - config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config, &out_table->string_pool, files, out_error); if (config_value->value == nullptr) { @@ -877,11 +875,12 @@ std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value, return value; } -std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, - const android::ResStringPool& src_pool, - const ConfigDescription& config, - android::StringPool* value_pool, - io::IFileCollection* files, std::string* out_error) { +std::unique_ptr<Item> DeserializeItemFromPbInternal(const pb::Item& pb_item, + const android::ResStringPool& src_pool, + const ConfigDescription& config, + android::StringPool* value_pool, + io::IFileCollection* files, + std::string* out_error) { switch (pb_item.value_case()) { case pb::Item::kRef: { const pb::Reference& pb_ref = pb_item.ref(); @@ -1010,6 +1009,19 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, return {}; } +std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, + const android::ResStringPool& src_pool, + const ConfigDescription& config, + android::StringPool* value_pool, + io::IFileCollection* files, std::string* out_error) { + auto item = + DeserializeItemFromPbInternal(pb_item, src_pool, config, value_pool, files, out_error); + if (item) { + item->SetFlagStatus((FlagStatus)pb_item.flag_status()); + } + return item; +} + std::unique_ptr<xml::XmlResource> DeserializeXmlResourceFromPb(const pb::XmlNode& pb_node, std::string* out_error) { if (!pb_node.has_element()) { diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index c1e15bcf9f70..5772b3b0b3e6 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -426,7 +426,6 @@ void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table pb_config_value->mutable_config()->set_product(config_value->product); SerializeValueToPb(*config_value->value, pb_config_value->mutable_value(), source_pool.get()); - pb_config_value->set_flag_status((uint32_t)config_value->flag_status); } } } @@ -720,6 +719,9 @@ void SerializeValueToPb(const Value& value, pb::Value* out_value, android::Strin if (src_pool != nullptr) { SerializeSourceToPb(value.GetSource(), src_pool, out_value->mutable_source()); } + if (out_value->has_item()) { + out_value->mutable_item()->set_flag_status((uint32_t)value.GetFlagStatus()); + } } void SerializeItemToPb(const Item& item, pb::Item* out_item) { @@ -727,6 +729,7 @@ void SerializeItemToPb(const Item& item, pb::Item* out_item) { ValueSerializer serializer(&value, nullptr); item.Accept(&serializer); out_item->MergeFrom(value.item()); + out_item->set_flag_status((uint32_t)item.GetFlagStatus()); } void SerializeCompiledFileToPb(const ResourceFile& file, pb::internal::CompiledFile* out_file) { diff --git a/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp b/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp index 5932271d4d28..4866d2c83c71 100644 --- a/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp +++ b/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp @@ -28,11 +28,13 @@ genrule { srcs: [ "res/values/bools.xml", "res/values/bools2.xml", + "res/values/ints.xml", "res/values/strings.xml", ], out: [ "values_bools.arsc.flat", "values_bools2.arsc.flat", + "values_ints.arsc.flat", "values_strings.arsc.flat", ], cmd: "$(location aapt2) compile $(in) -o $(genDir) " + diff --git a/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/ints.xml b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/ints.xml new file mode 100644 index 000000000000..26a5c40bb338 --- /dev/null +++ b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/ints.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <integer-array name="intarr1"> + <item>1</item> + <item>2</item> + <item android:featureFlag="test.package.falseFlag">666</item> + <item>3</item> + </integer-array> +</resources>
\ No newline at end of file diff --git a/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/strings.xml b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/strings.xml index 5c0fca16fe39..3cbb928a64cc 100644 --- a/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/strings.xml +++ b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/strings.xml @@ -3,4 +3,11 @@ <string name="str">plain string</string> <string name="str1" android:featureFlag="test.package.falseFlag">DONTFIND</string> + + <string-array name="strarr1"> + <item>one</item> + <item>two</item> + <item android:featureFlag="test.package.falseFlag">remove</item> + <item android:featureFlag="test.package.trueFlag">three</item> + </string-array> </resources>
\ No newline at end of file diff --git a/tools/aapt2/link/FlagDisabledResourceRemover.cpp b/tools/aapt2/link/FlagDisabledResourceRemover.cpp index e3289e2a173a..3ac17625023e 100644 --- a/tools/aapt2/link/FlagDisabledResourceRemover.cpp +++ b/tools/aapt2/link/FlagDisabledResourceRemover.cpp @@ -32,12 +32,17 @@ static bool KeepResourceEntry(const std::unique_ptr<ResourceEntry>& entry) { const auto remove_iter = std::stable_partition(entry->values.begin(), end_iter, [](const std::unique_ptr<ResourceConfigValue>& value) -> bool { - return value->flag_status != FlagStatus::Disabled; + return value->value->GetFlagStatus() != FlagStatus::Disabled; }); bool keep = remove_iter != entry->values.begin(); entry->values.erase(remove_iter, end_iter); + + for (auto& value : entry->values) { + value->value->RemoveFlagDisabledElements(); + } + return keep; } diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index 1942fc11c32e..37a039e9528f 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -212,8 +212,8 @@ static ResourceTable::CollisionResult MergeConfigValue( collision_result = ResolveMergeCollision(override_styles_instead_of_overlaying, dst_value, src_value, pool); } else { - collision_result = ResourceTable::ResolveFlagCollision(dst_config_value->flag_status, - src_config_value->flag_status); + collision_result = + ResourceTable::ResolveFlagCollision(dst_value->GetFlagStatus(), src_value->GetFlagStatus()); if (collision_result == CollisionResult::kConflict) { collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value); } @@ -295,7 +295,6 @@ bool TableMerger::DoMerge(const android::Source& src, ResourceTablePackage* src_ } else { dst_config_value = dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product); - dst_config_value->flag_status = src_config_value->flag_status; } // Continue if we're taking the new resource. diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt index 36bfbefdb086..7b086784761f 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt @@ -22,6 +22,7 @@ import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter import com.android.hoststubgen.filters.ConstantFilter import com.android.hoststubgen.filters.DefaultHookInjectingFilter import com.android.hoststubgen.filters.FilterPolicy +import com.android.hoststubgen.filters.FilterRemapper import com.android.hoststubgen.filters.ImplicitOutputFilter import com.android.hoststubgen.filters.OutputFilter import com.android.hoststubgen.filters.StubIntersectingFilter @@ -37,6 +38,7 @@ import org.objectweb.asm.commons.ClassRemapper import org.objectweb.asm.commons.Remapper import org.objectweb.asm.util.CheckClassAdapter import java.io.BufferedInputStream +import java.io.BufferedOutputStream import java.io.FileOutputStream import java.io.InputStream import java.io.OutputStream @@ -74,7 +76,9 @@ class HostStubGen(val options: HostStubGenOptions) { } // Build the filters. - val (filter, policyFileRemapper) = buildFilter(errors, allClasses, options) + val filter = buildFilter(errors, allClasses, options) + + val filterRemapper = FilterRemapper(filter) // Transform the jar. convert( @@ -86,7 +90,7 @@ class HostStubGen(val options: HostStubGenOptions) { allClasses, errors, stats, - policyFileRemapper, + filterRemapper, options.numShards.get, options.shard.get, ) @@ -116,7 +120,7 @@ class HostStubGen(val options: HostStubGenOptions) { errors: HostStubGenErrors, allClasses: ClassNodes, options: HostStubGenOptions, - ): Pair<OutputFilter, Remapper?> { + ): OutputFilter { // We build a "chain" of multiple filters here. // // The filters are build in from "inside", meaning the first filter created here is @@ -169,14 +173,10 @@ class HostStubGen(val options: HostStubGenOptions) { filter, ) - var policyFileRemapper: Remapper? = null - // Next, "text based" filter, which allows to override polices without touching // the target code. options.policyOverrideFile.ifSet { - val (f, p) = createFilterFromTextPolicyFile(it, allClasses, filter) - filter = f - policyFileRemapper = p + filter = createFilterFromTextPolicyFile(it, allClasses, filter) } // If `--intersect-stub-jar` is provided, load from these jar files too. @@ -191,7 +191,7 @@ class HostStubGen(val options: HostStubGenOptions) { // Apply the implicit filter. filter = ImplicitOutputFilter(errors, allClasses, filter) - return Pair(filter, policyFileRemapper) + return filter } /** @@ -273,7 +273,7 @@ class HostStubGen(val options: HostStubGenOptions) { if (filename == null) { return block(null) } - return ZipOutputStream(FileOutputStream(filename)).use(block) + return ZipOutputStream(BufferedOutputStream(FileOutputStream(filename))).use(block) } /** @@ -334,13 +334,14 @@ class HostStubGen(val options: HostStubGenOptions) { entry: ZipEntry, out: ZipOutputStream, ) { - BufferedInputStream(inZip.getInputStream(entry)).use { bis -> + // TODO: It seems like copying entries this way is _very_ slow, + // even with out.setLevel(0). Look for other ways to do it. + + inZip.getInputStream(entry).use { ins -> // Copy unknown entries as is to the impl out. (but not to the stub out.) val outEntry = ZipEntry(entry.name) out.putNextEntry(outEntry) - while (bis.available() > 0) { - out.write(bis.read()) - } + ins.transferTo(out) out.closeEntry() } } diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt index ee4a06fb983d..fcdf8247e7d0 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt @@ -121,7 +121,7 @@ class HostStubGenLogger { return level.ordinal <= maxLogLevel.ordinal } - private fun println(level: LogLevel, message: String) { + fun println(level: LogLevel, message: String) { printers.forEach { if (it.logLevel.ordinal >= level.ordinal) { it.println(level, indent, message) @@ -129,7 +129,7 @@ class HostStubGenLogger { } } - private fun println(level: LogLevel, format: String, vararg args: Any?) { + fun println(level: LogLevel, format: String, vararg args: Any?) { if (isEnabled(level)) { println(level, String.format(format, *args)) } @@ -185,14 +185,29 @@ class HostStubGenLogger { println(LogLevel.Debug, format, *args) } - inline fun <T> iTime(message: String, block: () -> T): T { + inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): T { val start = System.currentTimeMillis() - val ret = block() - val end = System.currentTimeMillis() + try { + return block() + } finally { + val end = System.currentTimeMillis() + if (isEnabled(level)) { + println(level, + String.format("%s: took %.1f second(s).", message, (end - start) / 1000.0)) + } + } + } - log.i("%s: took %.1f second(s).", message, (end - start) / 1000.0) + inline fun <T> iTime(message: String, block: () -> T): T { + return logTime(LogLevel.Info, message, block) + } + + inline fun <T> vTime(message: String, block: () -> T): T { + return logTime(LogLevel.Verbose, message, block) + } - return ret + inline fun <T> dTime(message: String, block: () -> T): T { + return logTime(LogLevel.Debug, message, block) } inline fun forVerbose(block: () -> Unit) { diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt index 3f2b13aed5c0..f219dac7f0a5 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt @@ -117,6 +117,14 @@ fun resolveClassNameWithDefaultPackage(className: String, defaultPackageName: St return "$defaultPackageName.$className" } +fun splitWithLastPeriod(name: String): Pair<String, String>? { + val pos = name.lastIndexOf('.') + if (pos < 0) { + return null + } + return Pair(name.substring(0, pos), name.substring(pos + 1)) +} + fun String.toJvmClassName(): String { return this.replace('.', '/') } @@ -198,11 +206,11 @@ fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) { /** * Given a method descriptor, insert an [argType] as the first argument to it. */ -fun prependArgTypeToMethodDescriptor(methodDescriptor: String, argType: Type): String { +fun prependArgTypeToMethodDescriptor(methodDescriptor: String, classInternalName: String): String { val returnType = Type.getReturnType(methodDescriptor) val argTypes = Type.getArgumentTypes(methodDescriptor).toMutableList() - argTypes.add(0, argType) + argTypes.add(0, Type.getType("L" + classInternalName + ";")) return Type.getMethodDescriptor(returnType, *argTypes.toTypedArray()) } diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt index cdd24e809ff8..6fcffb89924a 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt @@ -87,4 +87,23 @@ abstract class DelegatingFilter( ): List<String> { return fallback.getMethodCallHooks(className, methodName, descriptor) } + + override fun remapType(className: String): String? { + return fallback.remapType(className) + } + + override fun hasAnyMethodCallReplace(): Boolean { + return fallback.hasAnyMethodCallReplace() + } + + override fun getMethodCallReplaceTo( + callerClassName: String, + callerMethodName: String, + className: String, + methodName: String, + descriptor: String, + ): MethodReplaceTarget? { + return fallback.getMethodCallReplaceTo( + callerClassName, callerMethodName, className, methodName, descriptor) + } } diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt index 4d211065f1c8..f839444abb46 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt @@ -70,7 +70,7 @@ enum class FilterPolicy { get() = this == SubstituteAndStub || this == SubstituteAndKeep val needsInStub: Boolean - get() = this == Stub || this == StubClass || this == SubstituteAndStub + get() = this == Stub || this == StubClass || this == SubstituteAndStub || this == Ignore val needsInImpl: Boolean get() = this != Remove diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt new file mode 100644 index 000000000000..c5a2f9ff5e96 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterRemapper.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import org.objectweb.asm.commons.Remapper + +/** + * A [Remapper] that uses [OutputFilter.remapType] + */ +class FilterRemapper(val filter: OutputFilter) : Remapper() { + private val cache = mutableMapOf<String, String>() + + override fun mapType(typeInternalName: String?): String? { + if (typeInternalName == null) { + return null + } + + cache[typeInternalName]?.let { + return it + } + + var mapped = filter.remapType(typeInternalName) ?: typeInternalName + cache[typeInternalName] = mapped + return mapped + } + + // TODO Do we need to implement mapPackage(), etc too? +}
\ No newline at end of file diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt index 3df16ffa99b3..1049e2bf94cf 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt @@ -89,4 +89,35 @@ abstract class OutputFilter { List<String> { return emptyList() } -}
\ No newline at end of file + + /** + * Take a class (internal) name. If the class needs to be renamed, return the new name. + * This is used by [FilterRemapper]. + */ + open fun remapType(className: String): String? { + return null + } + + data class MethodReplaceTarget(val className: String, val methodName: String) + + /** + * Return if this filter may return non-null from [getMethodCallReplaceTo]. + * (Used for a small optimization) + */ + open fun hasAnyMethodCallReplace(): Boolean { + return false + } + + /** + * If a method call should be forwarded to another method, return the target's class / method. + */ + open fun getMethodCallReplaceTo( + callerClassName: String, + callerMethodName: String, + className: String, + methodName: String, + descriptor: String, + ): MethodReplaceTarget? { + return null + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt index 18280034c2f4..53bcf103cad4 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt @@ -17,12 +17,13 @@ package com.android.hoststubgen.filters import com.android.hoststubgen.ParseException import com.android.hoststubgen.asm.ClassNodes +import com.android.hoststubgen.asm.splitWithLastPeriod import com.android.hoststubgen.asm.toHumanReadableClassName +import com.android.hoststubgen.asm.toJvmClassName import com.android.hoststubgen.log import com.android.hoststubgen.normalizeTextLine import com.android.hoststubgen.whitespaceRegex import org.objectweb.asm.Opcodes -import org.objectweb.asm.commons.Remapper import org.objectweb.asm.tree.ClassNode import java.io.BufferedReader import java.io.FileReader @@ -62,7 +63,7 @@ fun createFilterFromTextPolicyFile( filename: String, classes: ClassNodes, fallback: OutputFilter, - ): Pair<OutputFilter, Remapper?> { + ): OutputFilter { log.i("Loading offloaded annotations from $filename ...") log.withIndent { val subclassFilter = SubclassFilter(classes, fallback) @@ -75,7 +76,9 @@ fun createFilterFromTextPolicyFile( var featureFlagsPolicy: FilterPolicyWithReason? = null var syspropsPolicy: FilterPolicyWithReason? = null var rFilePolicy: FilterPolicyWithReason? = null - val typeRenameSpec = mutableListOf<TextFilePolicyRemapper.TypeRenameSpec>() + val typeRenameSpec = mutableListOf<TextFilePolicyRemapperFilter.TypeRenameSpec>() + val methodReplaceSpec = + mutableListOf<TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec>() try { BufferedReader(FileReader(filename)).use { reader -> @@ -250,8 +253,24 @@ fun createFilterFromTextPolicyFile( policy.getSubstitutionBasePolicy() .withReason(FILTER_REASON)) - // Keep "from" -> "to" mapping. - imf.setRenameTo(className, fromName, signature, name) + val classAndMethod = splitWithLastPeriod(fromName) + if (classAndMethod != null) { + // If the substitution target contains a ".", then + // it's a method call redirect. + methodReplaceSpec.add( + TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec( + className.toJvmClassName(), + name, + signature, + classAndMethod.first.toJvmClassName(), + classAndMethod.second, + ) + ) + } else { + // It's an in-class replace. + // ("@RavenwoodReplace" equivalent) + imf.setRenameTo(className, fromName, signature, name) + } } } "r", "rename" -> { @@ -267,7 +286,7 @@ fun createFilterFromTextPolicyFile( // applied. (Which is needed for services.jar) val prefix = fields[2].trimStart('/') - typeRenameSpec += TextFilePolicyRemapper.TypeRenameSpec( + typeRenameSpec += TextFilePolicyRemapperFilter.TypeRenameSpec( pattern, prefix) } @@ -281,16 +300,19 @@ fun createFilterFromTextPolicyFile( throw e.withSourceInfo(filename, lineNo) } - var remapper: TextFilePolicyRemapper? = null + var ret: OutputFilter = imf if (typeRenameSpec.isNotEmpty()) { - remapper = TextFilePolicyRemapper(typeRenameSpec) + ret = TextFilePolicyRemapperFilter(typeRenameSpec, ret) + } + if (methodReplaceSpec.isNotEmpty()) { + ret = TextFilePolicyMethodReplaceFilter(methodReplaceSpec, classes, ret) } // Wrap the in-memory-filter with AHF. - return Pair( - AndroidHeuristicsFilter( - classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, imf), - remapper) + ret = AndroidHeuristicsFilter( + classes, aidlPolicy, featureFlagsPolicy, syspropsPolicy, rFilePolicy, ret) + + return ret } } @@ -330,6 +352,7 @@ private fun parsePolicy(s: String): FilterPolicy { "r", "remove" -> FilterPolicy.Remove "sc", "stubclass" -> FilterPolicy.StubClass "kc", "keepclass" -> FilterPolicy.KeepClass + "i", "ignore" -> FilterPolicy.Ignore else -> { if (s.startsWith("@")) { FilterPolicy.SubstituteAndStub diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyMethodReplaceFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyMethodReplaceFilter.kt new file mode 100644 index 000000000000..d45f41407a52 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyMethodReplaceFilter.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.filters + +import com.android.hoststubgen.asm.ClassNodes + +/** + * Filter used by TextFileFilterPolicyParser for "method call relacement". + */ +class TextFilePolicyMethodReplaceFilter( + val spec: List<MethodCallReplaceSpec>, + val classes: ClassNodes, + val fallback: OutputFilter, +) : DelegatingFilter(fallback) { + + data class MethodCallReplaceSpec( + val fromClass: String, + val fromMethod: String, + val fromDescriptor: String, + val toClass: String, + val toMethod: String, + ) + + override fun hasAnyMethodCallReplace(): Boolean { + return true + } + + override fun getMethodCallReplaceTo( + callerClassName: String, + callerMethodName: String, + className: String, + methodName: String, + descriptor: String, + ): MethodReplaceTarget? { + // Maybe use 'Tri' if we end up having too many replacements. + spec.forEach { + if (className == it.fromClass && + methodName == it.fromMethod && + descriptor == it.fromDescriptor + ) { + return MethodReplaceTarget(it.toClass, it.toMethod) + } + } + return null + } +} diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt index 2d94bb4758ba..a78c6552b8d0 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapper.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFilePolicyRemapperFilter.kt @@ -16,15 +16,15 @@ package com.android.hoststubgen.filters import com.android.hoststubgen.log -import org.objectweb.asm.commons.Remapper import java.util.regex.Pattern /** - * A [Remapper] that provides a simple "jarjar" functionality. + * A filter that provides a simple "jarjar" functionality via [mapType] */ -class TextFilePolicyRemapper( - val typeRenameSpecs: List<TypeRenameSpec> -) : Remapper() { +class TextFilePolicyRemapperFilter( + val typeRenameSpecs: List<TypeRenameSpec>, + fallback: OutputFilter, +) : DelegatingFilter(fallback) { /** * When a package name matches [typeInternalNamePattern], we prepend [typeInternalNamePrefix] * to it. @@ -36,24 +36,15 @@ class TextFilePolicyRemapper( private val cache = mutableMapOf<String, String>() - override fun mapType(typeInternalName: String): String { -// if (typeInternalName == null) { -// return null // do we need it?? -// } - cache[typeInternalName]?.let { - return it - } - - var mapped: String = typeInternalName + override fun remapType(className: String): String? { + var mapped: String = className typeRenameSpecs.forEach { - if (it.typeInternalNamePattern.matcher(typeInternalName).matches()) { - mapped = it.typeInternalNamePrefix + typeInternalName - log.d("Renaming type $typeInternalName to $mapped") + if (it.typeInternalNamePattern.matcher(className).matches()) { + mapped = it.typeInternalNamePrefix + className + log.d("Renaming type $className to $mapped") } } - cache[typeInternalName] = mapped + cache[className] = mapped return mapped } - - // TODO Do we need to implement mapPackage(), etc too? } diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt index 416b78242899..3d2e1429a30f 100644 --- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt +++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt @@ -33,6 +33,9 @@ import com.android.hoststubgen.log import org.objectweb.asm.ClassVisitor import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes +import org.objectweb.asm.Opcodes.INVOKEINTERFACE +import org.objectweb.asm.Opcodes.INVOKESTATIC +import org.objectweb.asm.Opcodes.INVOKEVIRTUAL import org.objectweb.asm.Type /** @@ -211,17 +214,14 @@ class ImplGeneratingAdapter( } if (policy.policy == FilterPolicy.Ignore) { - when (Type.getReturnType(descriptor)) { - Type.VOID_TYPE -> { - log.v("Making method ignored...") - return IgnoreMethodAdapter( - access, name, descriptor, signature, exceptions, innerVisitor) - .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR) - } - else -> { - throw RuntimeException("Ignored policy only allowed for void methods") - } - } + log.v("Making method ignored...") + return IgnoreMethodAdapter( + access, name, descriptor, signature, exceptions, innerVisitor) + .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR) + } + if (filter.hasAnyMethodCallReplace()) { + innerVisitor = MethodCallReplacingAdapter( + access, name, descriptor, signature, exceptions, innerVisitor) } } if (substituted) { @@ -290,14 +290,37 @@ class ImplGeneratingAdapter( */ private inner class IgnoreMethodAdapter( access: Int, - val name: String, - descriptor: String, + name: String, + val descriptor: String, signature: String?, exceptions: Array<String>?, next: MethodVisitor? ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) { override fun emitNewCode() { - visitInsn(Opcodes.RETURN) + when (Type.getReturnType(descriptor)) { + Type.VOID_TYPE -> visitInsn(Opcodes.RETURN) + Type.BOOLEAN_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE, Type.SHORT_TYPE, + Type.INT_TYPE -> { + visitInsn(Opcodes.ICONST_0) + visitInsn(Opcodes.IRETURN) + } + Type.LONG_TYPE -> { + visitInsn(Opcodes.LCONST_0) + visitInsn(Opcodes.LRETURN) + } + Type.FLOAT_TYPE -> { + visitInsn(Opcodes.FCONST_0) + visitInsn(Opcodes.FRETURN) + } + Type.DOUBLE_TYPE -> { + visitInsn(Opcodes.DCONST_0) + visitInsn(Opcodes.DRETURN) + } + else -> { + visitInsn(Opcodes.ACONST_NULL) + visitInsn(Opcodes.ARETURN) + } + } visitMaxs(0, 0) // We let ASM figure them out. } } @@ -332,11 +355,9 @@ class ImplGeneratingAdapter( // Update the descriptor -- add this class's type as the first argument // to the method descriptor. - val thisType = Type.getType("L" + currentClassName + ";") - targetDescriptor = prependArgTypeToMethodDescriptor( - descriptor, - thisType, + descriptor, + currentClassName, ) // Shift the original arguments by one. @@ -451,4 +472,61 @@ class ImplGeneratingAdapter( false) } } + + private inner class MethodCallReplacingAdapter( + access: Int, + val callerMethodName: String, + val descriptor: String, + signature: String?, + exceptions: Array<String>?, + next: MethodVisitor?, + ) : MethodVisitor(OPCODE_VERSION, next) { + override fun visitMethodInsn( + opcode: Int, + owner: String?, + name: String?, + descriptor: String?, + isInterface: Boolean, + ) { + when (opcode) { + INVOKESTATIC, INVOKEVIRTUAL, INVOKEINTERFACE -> {} + else -> { + // Don't touch other opcodes. + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + return + } + } + val to = filter.getMethodCallReplaceTo( + currentClassName, callerMethodName, owner!!, name!!, descriptor!!) + + if (to == null + // Don't replace if the target is the callsite. + || (to.className == currentClassName && to.methodName == callerMethodName) + ) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + return + } + + // Replace the method call with a (static) call to the target method. + // If it's a non-static call, the target method's first argument will receive "this". + // (Because of that, we don't need to manipulate the stack. Just replace the + // method call.) + + val toDesc = if (opcode == INVOKESTATIC) { + // Static call to static call, no need to change the desc. + descriptor + } else { + // Need to prepend the "this" type to the descriptor. + prependArgTypeToMethodDescriptor(descriptor, owner) + } + + mv.visitMethodInsn( + INVOKESTATIC, + to.className, + to.methodName, + toDesc, + false + ) + } + } } diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt index c127e677f84d..c2f593cf5ae3 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt @@ -1436,7 +1436,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object - interfaces: 0, fields: 3, methods: 10, attributes: 1 + interfaces: 0, fields: 3, methods: 19, attributes: 1 public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1513,6 +1513,132 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; 0 8 1 foo Ljava/lang/String; + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + public int addTwo(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC @@ -1897,6 +2023,174 @@ BootstrapMethods: InnerClasses: public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 thread Ljava/lang/Thread; + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + 0 4 1 b I +} +SourceFile: "TinyFrameworkMethodCallReplace.java" +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 5, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=0 + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 9 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 23 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method originalAdd:(II)I + x: ireturn + LineNumberTable: + + private static int originalAdd(int, int); + descriptor: (II)I + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: iconst_1 + x: isub + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 a I + 0 6 1 b I + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; +} +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class Compiled from "TinyFrameworkNative.java" public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt index 17ba48c67d98..1b83d244c55c 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt @@ -1197,7 +1197,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object - interfaces: 0, fields: 1, methods: 5, attributes: 2 + interfaces: 0, fields: 1, methods: 14, attributes: 2 public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1239,6 +1239,150 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli x: #x() com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public int addTwo(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC @@ -1640,6 +1784,161 @@ RuntimeInvisibleAnnotations: android.hosttest.annotation.HostSideTestStaticInitializerKeep NestMembers: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class Compiled from "TinyFrameworkNative.java" public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt index 0f5f7e747a2e..d23b450c4076 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt @@ -1730,7 +1730,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object - interfaces: 0, fields: 2, methods: 8, attributes: 2 + interfaces: 0, fields: 2, methods: 17, attributes: 2 public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1825,6 +1825,140 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli x: #x() com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aconst_null + x: areturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=0, locals=1, args_size=1 + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: fconst_0 + x: freturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: dconst_0 + x: dreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public int addTwo(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC @@ -2330,6 +2464,202 @@ BootstrapMethods: #x ()Ljava/lang/Integer; NestMembers: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 thread Ljava/lang/Thread; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + 0 4 1 b I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 6 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=0 + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.startThread:(Ljava/lang/Thread;)V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 9 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 23 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.add:(II)I + x: ireturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class Compiled from "TinyFrameworkNative.java" public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt index 17ba48c67d98..1b83d244c55c 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt @@ -1197,7 +1197,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object - interfaces: 0, fields: 1, methods: 5, attributes: 2 + interfaces: 0, fields: 1, methods: 14, attributes: 2 public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1239,6 +1239,150 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli x: #x() com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public int addTwo(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC @@ -1640,6 +1784,161 @@ RuntimeInvisibleAnnotations: android.hosttest.annotation.HostSideTestStaticInitializerKeep NestMembers: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Stub! + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class Compiled from "TinyFrameworkNative.java" public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt index 3beea643823a..d12a23d3d68f 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt @@ -2141,7 +2141,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object - interfaces: 0, fields: 2, methods: 8, attributes: 2 + interfaces: 0, fields: 2, methods: 17, attributes: 2 public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2254,13 +2254,192 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli x: #x() com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredObj + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aconst_null + x: areturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredV + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredZ + x: ldc #x // String ()Z + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredB + x: ldc #x // String ()B + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredC + x: ldc #x // String ()C + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredS + x: ldc #x // String ()S + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredI + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredF + x: ldc #x // String ()F + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: fconst_0 + x: freturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredD + x: ldc #x // String ()D + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: dconst_0 + x: dreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + public int addTwo(int); descriptor: (I)I flags: (0x0001) ACC_PUBLIC Code: stack=4, locals=2, args_size=2 x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy - x: ldc #x // String addTwo + x: ldc #x // String addTwo x: ldc #x // String (I)I x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V @@ -2287,7 +2466,7 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli Code: stack=4, locals=1, args_size=1 x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy - x: ldc #x // String nativeAddThree + x: ldc #x // String nativeAddThree x: ldc #x // String (I)I x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V @@ -2313,21 +2492,21 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli Code: stack=4, locals=1, args_size=1 x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy - x: ldc #x // String unsupportedMethod + x: ldc #x // String unsupportedMethod x: ldc #x // String ()Ljava/lang/String; x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy - x: ldc #x // String unsupportedMethod + x: ldc #x // String unsupportedMethod x: ldc #x // String ()Ljava/lang/String; x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker; x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class; x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V - x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V - x: new #x // class java/lang/RuntimeException + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException x: dup - x: ldc #x // String Unreachable - x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V x: athrow RuntimeVisibleAnnotations: x: #x() @@ -2341,12 +2520,12 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli Code: stack=4, locals=1, args_size=1 x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy - x: ldc #x // String visibleButUsesUnsupportedMethod + x: ldc #x // String visibleButUsesUnsupportedMethod x: ldc #x // String ()Ljava/lang/String; x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V x: aload_0 - x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; + x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String; x: areturn LineNumberTable: LocalVariableTable: @@ -2865,6 +3044,257 @@ BootstrapMethods: #x ()Ljava/lang/Integer; NestMembers: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String startThread + x: ldc #x // String (Ljava/lang/Thread;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 thread Ljava/lang/Thread; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String add + x: ldc #x // String (II)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 a I + 11 4 1 b I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 61 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 5, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String nonStaticMethodCallReplaceTester + x: ldc #x // String ()Z + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.startThread:(Ljava/lang/Thread;)V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 20 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 34 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String staticMethodCallReplaceTester + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.add:(II)I + x: ireturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0 + x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInStub + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassStub +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class Compiled from "TinyFrameworkNative.java" public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt index 75c9721020bd..f06443362b1d 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt @@ -12,6 +12,16 @@ class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub # method addThree_host (I)I # used as a substitute method unsupportedMethod ()Ljava/lang/String; throw method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub + method toBeIgnoredObj ()Ljava/lang/String; ignore + method toBeIgnoredV ()V ignore + method toBeIgnoredZ ()Z ignore + method toBeIgnoredB ()B ignore + method toBeIgnoredC ()C ignore + method toBeIgnoredS ()S ignore + method toBeIgnoredI ()I ignore + method toBeIgnoredL ()L ignore + method toBeIgnoredF ()F ignore + method toBeIgnoredD ()D ignore # Class load hook class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded @@ -49,8 +59,18 @@ class com.android.hoststubgen.test.tinyframework.packagetest.sub.B remove # class com.android.hoststubgen.test.tinyframework.packagetest.A stub # class com.android.hoststubgen.test.tinyframework.packagetest.sub.A stub +# Used to test method call replacement. +class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace stubclass + method originalAdd (II)I @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.add + +# Used to test method call replacement. +# Note because java.lang.Thread is _not_ within the tiny-framework jar, the policy ("keep") +# doesn't realy matter. +class java.lang.Thread keep + method start ()V @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.startThread + # "rename" takes a type internal name, so '/'s is used as a separator. # The leading / in the prefix is not needed (it'll be stripped), but it's added to make # sure the stripping works. -rename ^.*/TinyFrameworkToBeRenamed$ /rename_prefix/
\ No newline at end of file +rename ^.*/TinyFrameworkToBeRenamed$ /rename_prefix/ diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java index bde7c35dc294..1977c900ba11 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java @@ -42,6 +42,42 @@ public class TinyFrameworkForTextPolicy { throw new RuntimeException(); } + public String toBeIgnoredObj() { + throw new RuntimeException(); + } + + public void toBeIgnoredV() { + throw new RuntimeException(); + } + + public boolean toBeIgnoredZ() { + throw new RuntimeException(); + } + + public byte toBeIgnoredB() { + throw new RuntimeException(); + } + + public char toBeIgnoredC() { + throw new RuntimeException(); + } + + public short toBeIgnoredS() { + throw new RuntimeException(); + } + + public int toBeIgnoredI() { + throw new RuntimeException(); + } + + public float toBeIgnoredF() { + throw new RuntimeException(); + } + + public double toBeIgnoredD() { + throw new RuntimeException(); + } + public int addTwo(int value) { throw new RuntimeException("not supported on host side"); } diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java new file mode 100644 index 000000000000..1ff37441c262 --- /dev/null +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.hoststubgen.test.tinyframework; + +import android.hosttest.annotation.HostSideTestWholeClassStub; + +import java.util.concurrent.atomic.AtomicBoolean; + +@HostSideTestWholeClassStub +public class TinyFrameworkMethodCallReplace { + // This method should return true. + public static boolean nonStaticMethodCallReplaceTester() throws Exception { + final AtomicBoolean ab = new AtomicBoolean(false); + + Thread th = new Thread(() -> { + ab.set(Thread.currentThread().isDaemon()); + }); + // This Thread.start() call will be redirected to ReplaceTo.startThread() + // (because of the policy file directive) which will make the thread "daemon" and start it. + th.start(); + th.join(); + + return ab.get(); // This should be true. + } + + public static int staticMethodCallReplaceTester() { + // This method call will be replaced with ReplaceTo.add(). + return originalAdd(1, 2); + } + + private static int originalAdd(int a, int b) { + return a + b - 1; // Original is broken. + } + + public static class ReplaceTo { + public static void startThread(Thread thread) { + thread.setDaemon(true); + thread.start(); + } + + public static int add(int a, int b) { + return a + b; + } + } +} diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java index bf0f6545d1f5..1692c6e89e8c 100644 --- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java +++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java @@ -53,6 +53,20 @@ public class TinyFrameworkClassTest { // } @Test + public void testIgnore() { + TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); + tfc.toBeIgnoredV(); + assertThat(tfc.toBeIgnoredZ()).isEqualTo(false); + assertThat(tfc.toBeIgnoredB()).isEqualTo(0); + assertThat(tfc.toBeIgnoredC()).isEqualTo(0); + assertThat(tfc.toBeIgnoredS()).isEqualTo(0); + assertThat(tfc.toBeIgnoredI()).isEqualTo(0); + assertThat(tfc.toBeIgnoredF()).isEqualTo(0); + assertThat(tfc.toBeIgnoredD()).isEqualTo(0); + assertThat(tfc.toBeIgnoredObj()).isEqualTo(null); + } + + @Test public void testSubstitute() { TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy(); assertThat(tfc.addTwo(1)).isEqualTo(3); @@ -339,4 +353,16 @@ public class TinyFrameworkClassTest { public void testTypeRename() { assertThat(TinyFrameworkRenamedClassCaller.foo(1)).isEqualTo(1); } + + @Test + public void testMethodCallReplaceNonStatic() throws Exception { + assertThat(TinyFrameworkMethodCallReplace.nonStaticMethodCallReplaceTester()) + .isEqualTo(true); + } + + @Test + public void testMethodCallReplaceStatic() throws Exception { + assertThat(TinyFrameworkMethodCallReplace.staticMethodCallReplaceTester()) + .isEqualTo(3); + } } diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt index aa530050741b..22858803b597 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt @@ -26,7 +26,6 @@ import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.Modifier import com.github.javaparser.ast.NodeList import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration -import com.github.javaparser.ast.body.InitializerDeclaration import com.github.javaparser.ast.expr.ArrayAccessExpr import com.github.javaparser.ast.expr.ArrayCreationExpr import com.github.javaparser.ast.expr.ArrayInitializerExpr @@ -42,7 +41,10 @@ import com.github.javaparser.ast.expr.NullLiteralExpr import com.github.javaparser.ast.expr.ObjectCreationExpr import com.github.javaparser.ast.expr.SimpleName import com.github.javaparser.ast.expr.StringLiteralExpr +import com.github.javaparser.ast.expr.VariableDeclarationExpr import com.github.javaparser.ast.stmt.BlockStmt +import com.github.javaparser.ast.stmt.ReturnStmt +import com.github.javaparser.ast.type.ClassOrInterfaceType import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException @@ -195,6 +197,7 @@ object ProtoLogTool { groups: Map<String, LogGroup>, protoLogGroupsClassName: String ) { + var needsCreateLogGroupsMap = false classDeclaration.fields.forEach { field -> field.getAnnotationByClass(ProtoLogToolInjected::class.java) .ifPresent { annotationExpr -> @@ -222,33 +225,10 @@ object ProtoLogTool { } ?: NullLiteralExpr()) } ProtoLogToolInjected.Value.LOG_GROUPS.name -> { - val initializerBlockStmt = BlockStmt() - for (group in groups) { - initializerBlockStmt.addStatement( - MethodCallExpr() - .setName("put") - .setArguments( - NodeList(StringLiteralExpr(group.key), - FieldAccessExpr() - .setScope( - NameExpr( - protoLogGroupsClassName - )) - .setName(group.value.name))) - ) - group.key - } - - val treeMapCreation = ObjectCreationExpr() - .setType("TreeMap<String, IProtoLogGroup>") - .setAnonymousClassBody(NodeList( - InitializerDeclaration().setBody( - initializerBlockStmt - ) - )) - + needsCreateLogGroupsMap = true field.setFinal(true) - field.variables.first().setInitializer(treeMapCreation) + field.variables.first().setInitializer( + MethodCallExpr().setName("createLogGroupsMap")) } ProtoLogToolInjected.Value.CACHE_UPDATER.name -> { field.setFinal(true) @@ -261,6 +241,45 @@ object ProtoLogTool { } } } + + if (needsCreateLogGroupsMap) { + val body = BlockStmt() + body.addStatement(AssignExpr( + VariableDeclarationExpr( + ClassOrInterfaceType("TreeMap<String, IProtoLogGroup>"), + "result" + ), + ObjectCreationExpr().setType("TreeMap<String, IProtoLogGroup>"), + AssignExpr.Operator.ASSIGN + )) + for (group in groups) { + body.addStatement( + MethodCallExpr( + NameExpr("result"), + "put", + NodeList( + StringLiteralExpr(group.key), + FieldAccessExpr() + .setScope( + NameExpr( + protoLogGroupsClassName + )) + .setName(group.value.name) + ) + ) + ) + } + body.addStatement(ReturnStmt(NameExpr("result"))) + + val method = classDeclaration.addMethod( + "createLogGroupsMap", + Modifier.Keyword.PRIVATE, + Modifier.Keyword.STATIC, + Modifier.Keyword.FINAL + ) + method.setType("TreeMap<String, IProtoLogGroup>") + method.setBody(body) + } } private fun injectCacheClass( |